by Gabriel Mihalache

This is a quick note on a mostly pain-free way of saving and loading data for your Fortran code, with the best possible precision, while also
having the option to load the data in MATLAB (or similarly in any other "high level" language) with minimal hassle. As usual, your milleage may vary, *caveat emptor* and so on.

Say you have some fairly standard Fortran code, like this:

```
PROGRAM rbc
USE, INTRINSIC :: iso_Fortran_env, ONLY: wp => real64
IMPLICIT NONE
INTEGER, PARAMETER :: zSz = 25, kSz = 101
CHARACTER (LEN=*), PARAMETER :: outDir = "./results/"
REAL(wp), PARAMETER :: crra = 2.0_wp
INTEGER :: iunit
REAL(wp), DIMENSION(zSz, kSz) :: v0, v1
...
```

Eventually you will want to save your results, here the `v0`

array, for example:

```
OPEN(NEWUNIT=iunit, FILE=outDir // "v.bin", FORM="unformatted", ACCESS="stream", STATUS="unknown")
WRITE (iunit) v0
CLOSE(iunit)
```

The above will save the array to disk, in full `real64`

(a.k.a. `wp`

) precision, binary, without the need for specifying a format. Later, if you want to read back in this data, say for an initial guess, you can do so using something like:

```
OPEN(NEWUNIT=iunit, FILE=outdir // "v.bin", FORM="unformatted", ACCESS="stream", STATUS="old")
READ (iunit) v0
CLOSE(iunit)
```

That's pretty comfy. Now what about bringing those results into MATLAB for visualization, plotting, whatever? We should bring over all relevant parameters, array sizes, and the arrays themselves. First, let's write to a plain text file the parameters and dimensions of the problem, from Fortran:

```
OPEN(NEWUNIT=iunit, FILE=outDir // "parameters.txt")
WRITE (iunit, "(I20)") zSz
WRITE (iunit, "(I20)") kSz
WRITE (iunit, "(E20.10)") crra
...
CLOSE(iunit)
```

Here we *do* need to specify formats, because of the plain text format, but since we're only saving a handful of numbers we can live with it. `I20`

should be enough for any integer (up to 20 characters in length) and `E20.10`

will use scientific notation for our `real64`

-s. Now we're ready to read it in, in MATLAB:

```
params = dlmread('parameters.txt');
ix = 1;
zSz = params(ix); ix = ix + 1;
kSz = params(ix); ix = ix + 1;
crra = params(ix); ix = ix + 1;
...
clear params ix;
```

What about `v0`

? We know its dimensions, since we just read the parameters, including `zSz`

and `kSz`

, so we should use that programatically, in case we want to change the dimensions of the problem in future runs:

`v = loadBinary('v.bin', 'float64', [zSz, kSz]);`

Note that throughout I assumed that the MATLAB scripts are in the same directory/folder as the output of the Fortran code. Otherwise, adjust your paths accordingly. What about this `loadBinary`

function and `'float64'`

, what's that about? The function we need to write outselves, just once, for our convenience:

```
function [ out ] = loadBinary(fname, type, sz)
fileid = fopen(fname, 'r');
out = fread(fileid, [prod(sz), 1], type);
fclose(fileid);
out = reshape(out, sz);
end
```

The above function will load binary data from disk, based on the size and shape provided, then reshape it and return it to you neatly. We're not doing any error correction or attempt to gracefully recover from dimension/shape errors because if the sizes don't match, execution *should* stop with an error.

Concerning data types and their size in bytes... Fortran's `real64`

(also known as `DOUBLE REAL`

to some) matches MATLAB's `float64`

. Fortran's `INTEGER`

goes with `int32`

in MATLAB, and so on. The MATLAB documentation of `fread`

lists the data types. If you're trying to use the wrong data type, the size of the file will not match the `fread`

call and you'll get an error from MATLAB. You can check out this handy page on the Fortran Wiki about what predetermined data types you can find in `iso_fortran_env`

, my recommendation is to stick with those, for both `REAL`

s and `INTEGER`

s. I am also enthusiastic about the use of `LOGICAL`

variables to encode settings/flags.

A final note... if your code uses the GPU, often GPUs have far better performance in "single precision" mode, so you might want to use that instead:

`USE, INTRINSIC :: iso_Fortran_env, ONLY: wp => real32`