1

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?

Richard Rublev
  • 7,718
  • 16
  • 77
  • 121

2 Answers2

4

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)
Community
  • 1
  • 1
0

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.

d_1999
  • 854
  • 6
  • 16
  • I can compile with your suggestions and sizeof integer 32,but values are strange in vel.mod,something is wrong.Will edit my question. – Richard Rublev Jun 14 '16 at 15:37
  • @RichardRublev Storage size is numbers of bits. You would probably be better with stream access instead of direct anyway. – Vladimir F Героям слава Jun 14 '16 at 15:39
  • @VladimirF Thanks I missed the divide by 8. As you say stream is probably the way to go. – d_1999 Jun 14 '16 at 15:51
  • @IanH Many thanks for this, one of the reasons I answer questions is to learn (although I of course try to ensure I'm correct first). I'm going to edit this into the answer as an update so that future readers are not misled by my original statement. – d_1999 Jun 15 '16 at 07:51