Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28632 Discussions

a problem using ifort with direct access files

Donald_K_
Beginner
836 Views
Hi,

I use Intel Fortran Compiler for Intel EM64T-based applications, Version 9.0 Build 20050430 Package ID: l_fc_p_9.0.021.

I have a user defined type

type my
integer(kind=4) :: i
real(kind=8) :: x(3),a,b
end type my

I expect record length 44, as portland group, absoft and g95 fortran compilers report. Intel gives reports record length 48, as if it treats the integer as integer(kind=8).
The problem is that if a direct access file is written from a program compiled with ifort it cannot be read only from programs compiled with ifort.

I compile the program (attached) with:
#> ifort -assume byterecl if_reclen.f90
and execute:
#> a.out
so_reclen 48
si 22 1.000 2.000 3.000 4.000 5.000

What do I miss?
Thanks in advance, ted

program if_reclen
implicit none
type my
integer(kind=4) :: i
real(kind=8) :: x(3),a,b
end type my

type(my) :: so,si
integer(kind=4) :: rl

so%i=22
so%x=(/1.,2.,3./)
so%a=4.
so%b=5.

inquire(iolength=rl) so

print*, "so_reclen", rl

open(unit=9,file='test.da',form='unformatted',recl=rl,access='direct')
write(unit=9,rec=1) so
close(9)

open(unit=9,file='test.da',form='unformatted',recl=rl,access='direct')
read(unit=9,rec=1) si
write(*,'(a,i6,6f8.3)')'si ',si%i,si%x(1:3),si%a,si%b
close(9)

end program if_reclen
0 Kudos
5 Replies
Steven_L_Intel1
Employee
836 Views
You missed that Intel Fortran naturally aligns fields in records by default. You can add SEQUENCE or use -noalign to turn off the padding.
0 Kudos
Donald_K_
Beginner
836 Views
Hi,





I use 'sequence' or/and '-noalign' but get the same result: random


access files written with executable compiled with ifort are readable


only from applications compiled with ifort. Attached is a simple


program that writes and reads direct access data. The attached shell


script compiles if_reclen.f90 with absoft, portland, intel and g95


compilers, writes four random access files and reads them. What else


do I miss?








# CREATE af.exe, pg.exe, if.exe, g.exe EXECUTABLES





af90 -o af.exe -H60 -xINTEGER -N26 -lU77 if_reclen.f90


pgf90 -o pg.exe -Mbyteswapio -Bstatic -fastsse -Munroll=n:4 if_reclen.f90


ifort -o if.exe -convert big_endian -assume byterecl -noalign if_reclen.f90


export G95_ENDIAN=BIG ; g95 -o g.exe if_reclen.f90





# CREATE af.dat, if.dat, pg.dat, g.dat RANDOM ACCESS FILES:


af.exe af.dat w; if.exe if.dat w; pg.exe pg.dat w; g.exe g.dat w





# READ RANDOM ACCESS FILES


g.exe af.dat r


#> so_reclen 44


#> si 22 1.000 2.000 3.000 4.000 5.000





g.exe pg.dat r


#> so_reclen 44


#> si 22 1.000 2.000 3.000 4.000 5.000





g.exe if.dat r


#> so_reclen 44


#> si ****** 0.000 0.000 0.000 0.000 0.000








if.exe g.dat r


#> so_reclen 44


#> si ****** 0.000 0.000 0.000 0.000 0.000





if.exe pg.dat r


#> so_reclen 44


#> si ****** 0.000 0.000 0.000 0.000 0.000





if.exe af.dat r


#> so_reclen 44


#> si ****** 0.000 0.000 0.000 0.000 0.000





if.exe if.dat r


#> so_reclen 44


#> si 22 1.000 2.000 3.000 4.000 5.000





!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


program if_reclen


implicit none


integer(kind=4) :: iargc,numarg


character ( len = 80 ) fn,me


character ( len = 1 ) arg2





type my


sequence


integer(kind=4) :: i


real(kind=8) :: x(3),a,b


end type my





type(my) :: so,si


integer :: rl








numarg = iargc( )


call getarg(0,me)





if(numarg.lt.1) then


print*,"USAGE: "//trim(me), " ['r'|'w'] "


stop


end if





arg2='r'


call getarg(1,fn)


if(numarg.eq.2) call getarg(2,arg2)





so%i=22


so%x=(/1.,2.,3./)


so%a=4.


so%b=5.





inquire(iolength=rl) so


print*, "so_reclen", rl





if (arg2.eq.'r') then


call rd(fn)


else


call wr(fn)


call rd(fn)


end if








contains


subroutine wr(fn)


character(len=*),intent(in) :: fn


open(unit=9,file=fn,form='unformatted',recl=rl,access='direct')


write(unit=9,rec=1) so


write(unit=9,rec=2) so


write(unit=9,rec=3) so


close(9)


end subroutine wr





subroutine rd(fn)


character(len=*),intent(in) :: fn


integer(kind= 4) :: i


open(unit=9,file=fn,form='unformatted',recl=rl,access='direct',status='old')


read(unit=9,rec=2) si


write(*,'(a,i6,6f8.3)')'si ',si%i,si%x(1:3),si%a,si%b


close(9)


end subroutine rd





end program if_reclen
0 Kudos
Steven_L_Intel1
Employee
836 Views
You also missed that for unformatted, direct access files, the units of RECL= are 4-byte units by default. Use -assume byterecl to change this. This default has a 30+ year history.
0 Kudos
Donald_K_
Beginner
836 Views
I forgot to mention that I used to work with -assume byterecl but after I put 'sequence' I get record length 44 with and without '-assume byterecl'. Compiled with

ifort -o if.exe -convert big_endian -i4 -assume byterecl if_reclen.f90

I still I get:

g.exe af.dat r
so_reclen 44
si 22 1.000 2.000 3.000 4.000 5.000
g.exe pg.dat r
so_reclen 44
si 22 1.000 2.000 3.000 4.000 5.000

g.exe if.dat r
so_reclen 44
si ****** 0.000 0.000 0.000 0.000 0.000

I still miss something. Thanks, ts
0 Kudos
Steven_L_Intel1
Employee
836 Views
Why are you using -convert big_endian? I had not noticed that before. Unless your data file came from a big-endisn system, you should remove that.

-assume byterecl has nothing to do with the derived type length. It is used to compute byte offset in the file when you do direct access.

If you continue to have trouble, submit a support request to Intel Premier Support and attach your source file and a tar of your data file.
0 Kudos
Reply