Search code examples
matlabbinaryprecisionfortran90read-write

reading unformatted fortran file in matlab - which precision?


I have just written out a file:

 real*8                         :: vol_cel
 real*8, dimension(256,256,256) :: dense

[... some operations]

open(unit=8,file=fname,form="unformatted")
write(8)dense(:,:,:)/vol_cell
close(8)

My code to read this in in Matlab:

fid = fopen(fname,'r');
mesh_raw = fread(fid,256*256*256,'double');
fclose(fid);

The min and max values clearly show that it is not reading it in correctly (Min is 0 and max is a largish positive real*8).

min =
   3.3622e+38
max =
  -3.3661e+38

What precision do I need to set in Matlab to make it read in the unformatted Fortran file?

A somewhat related question: This Matlab code I am using reads binary files OK but not unformatted files. Though I am generating this new data on my Mac OSX using gfortran. It doesn't recognize form="binary" so I can't do it that way. Do I need to add some library or this an endian problem?

===== Progress =====

OK progress. Instead of my ndim*ndim*ndim matrix I just wrote out the x values (column vector) as such:

open(unit=8,file=fnamex,form="unformatted")
write(8)x0
close(8)

Then Matlab reads:

fid =    fopen(nfilename,'r');
hr3=fread(fid, 1, 'int32');
x0 = fread(fid,Ntot,'float32');
hr4=fread(fid, 1, 'int32');
fclose(fid);

THAT worked. Then I tried the original ndim**3 matrix, I tried to read with:

fid =    fopen(nfilename,'r');
hr3=fread(fid, 1, 'int32');
mesh_raw = fread(fid,ndim*ndim*ndim,'float32');
hr4=fread(fid, 1, 'int32');
fclose(fid);

But that gives me garbage. Perhaps here:

real*4,     dimension(:),   allocatable    :: x0
real*8,     dimension(256,256,256)         :: dense

Do I need to change: mesh_raw = fread(fid,ndim*ndim*ndim,'float32'); to make sure it is reading a real*8? What would that be? Surely just using 'real*8' verbatim should work? I mean 'real*4' for the x vector works. I mean it reads "dense" but the min/max/average values are wrong.


Solution

  • Your Fortran code shows you writing what is known as an unformatted sequential file. This is a record based file format. Typical implementation (Fortran compiler/platform specific) is for the compiler to write addition record structure information to the file - often (gfortran included) the record length is written at the start and end of each record. Your original Matlab code does not appear to take that into account.

    Fortran 2003 introduced stream access (add the ACCESS='STREAM' specifier to the OPEN statement). gfortran supports this feature, FORM='BINARY' is a non-standard synonym on some compilers. A unformatted file created with stream access has no record structure - it is a stream of bytes akin to a C stream. This may be more appropriate for you.