Richard Rublev
Richard Rublev

Reputation: 8172

Fortran write to binary:Fortran runtime error: Direct access data transfer requires record number

My code

program v3

implicit none

real :: xmin,xmax,ymin,ymax,zmin,zmax,size
integer :: nx,ny,nz,i,j,nodestotal,sizeofinteger
real,dimension(:), allocatable :: v
integer,dimension(:), allocatable :: v1
integer,dimension(:,:), allocatable :: vel

sizeofinteger=2

open(unit=34, file='for.header', status='old')
read(34,115) xmin,xmax,ymin,ymax,zmin,zmax,size,nx,ny,nz
115   format(7f10.3,3i10)

nodestotal=nx*ny*nz
allocate (v(nodestotal))
allocate (v1(nodestotal))
allocate (vel(nx,nz))

open(unit=35, file='vel.txt', status='unknown')
read(35,*)v

v1=nint(v)

vel=reshape(v1,(/ nx, nz /) )
write(*,*)vel(:,25)

open(unit=36, file='vel.mod', form='unformatted', access='direct', recl=nx*nz*sizeofinteger)
do i=1,nx
write(36)vel(i,:)
end do 

end program

How to specify the record length?I have not worked with FORTRAN binary files for a long time. What I really to write 601(nx) int 25(nz) times in binary file.I have changed sizeofinteger to 32.I want to write 2d array into binary file,should be simple. Following Vladimir F's advise I have changed to stream accesss,but this is what I got od -f vel.mod

1623500       8.688e-42               0               0               0
1623520               0               0               0               0
*
1625140       8.688e-42               0               0               0
1625160               0               0               0               0
*
1626600       8.688e-42               0               0               0
1626620               0               0               0               0
*
1630240       8.688e-42               0               0               0
1630260               0               0               0               0
*
1631700       8.688e-42               0               0               0
1631720               0               0               0               0
*
1633340       8.688e-42               0               0               0
1633360               0               0               0               0
*
1635000       8.688e-42               0               0               0
1635020               0               0               0               0
*
1636440       8.688e-42               0               0               0
1636460               0               0               0               0
*
1640100       8.688e-42               0               0               0
1640120               0               0               0               0
*
1641540       8.688e-42               0               0               0
1641560               0               0               0               0
*
1643200       8.688e-42               0               0               0
1643220               0               0               0               0
*
1644640       8.688e-42               0               0               0
1644660               0               0               0               0
*
1646300       8.688e-42               0               0               0
1646320               0               0               0               0
*
1647740       8.688e-42               0               0               0
1647760               0               0               0               0
*
1651400       8.688e-42               0               0               0
1651420               0               0               0               0
*
1653040

It should be 6200.Why?

Upvotes: 1

Views: 3024

Answers (2)

d_1999
d_1999

Reputation: 854

You have already specified the record length in your open statement (the recl argument). The error is actually complaining about the write statement. In your write statement you need to specify which record you're writing, so you could use

do i=1,nx
  write(36,rec=i)vel(i,:)
end do 

Aside

Note, as you are using unformatted the recl argument specifies the number of bytes per record.

The number of bytes per integer can be found using

sizeofinteger = storage_size(i)/8

and your record length would then be recl=sizeofinteger*nz.

Update

As has been pointed out in the comments by @IanH the recl argument is not always the number of bytes, it is in fact compiler dependent. As noted in the answer by @VladimirF one may determine the correct recl length an runtime using inquire to get the iolength.

Upvotes: 0

Very recently I said in an answer that people should not specify recl directly, but still so many do it... https://stackoverflow.com/a/37784431/721644

Use inquire(iolength=myrecl) as in that link and you will be much more portable.

Anyway, your code would be much simpler with stream access (resulting file is the same):

open(unit=36, file='vel.mod', form='unformatted', access='stream')
do i=1,nx
  write(36) vel(i,:)
end do 
close(36)

Upvotes: 4

Related Questions