Skip to content

Exodus Fortran Strangeness

Greg Sjaardema edited this page Feb 5, 2019 · 1 revision

There is some strangeness in the fortran API. There are typically two versions of the fortran library available:

  • libexodus_for.a
  • libexoIIv2for32.a

The “default” library libexodus_for.a is tailored for some assumptions we made a couple decades ago when we converted all of our pre and post processing executables to 64-bit capability. At the time, it was deemed easiest to use compiler options that automatically made all integers 8-bytes and all reals 8-bytes. We could then get 64-bit capability with no changes to our source code.

The other library libexoIIv2for32.a does not have this assumption and will have 32-bit integers by default and 32-bit reals by default. Both of these can be changed through the API – either on the exopen and excre calls for the real size and through another call for the integer sizes.

Issue with mixing of Fortran and C API and 64-bit integers

Although, in general, the modifications to exodus to permit the use of 8-byte integers for models exceeding 2.1 Billion nodes and or elements is backwards compatible, I think that some_code is one case where the changes are not backwards compatible. It looks like you are using both the Fortran and the C API to access the same file in the same execution. This is definitely possible and supported, but it does introduce some subtleties.

There are two fortran APIs useable with exodus. One of these uses the native word sizes (4-byte integers and 4-byte or 8-byte reals) and the other relies on a compiler flag to pass 8-byte integers and 8-byte reals. This API is the most used, at least internally by the SEACAS tools. It was originally implemented a couple decades ago as a simple means of converting existing exodus codes to use double precision real data without modifying the code.

In the past, this second API relied on wrapper routines in addrwrap.F which would pass the REAL (double precision) arrays through untouched, but would convert the 8-byte integers to 4-byte integers and then call the underlying C API function. All reals were 8-bytes and all integers were 4-byte by the time they hit the C API.

When we added the support for 8-byte integers to exodus, we had the option of passing 8-byte integers through the API and they would either go to disk as 8-bytes or 4-bytes depending on settings. If converted from 8-byte to 4-byte, this was handled by the underlying NetCDF library.

At that time, we were able to simplify the addrwrap.F implementation since we no longer had to down-convert the integers from 8-byte to 4-byte – we would tell the C API to expect 8-byte integers and then the underlying NetCDF library would either convert to 4-byte or would output 8-byte. This simplified addrwrap.F and gave the option to store 8-byte integers through the Fortran API. This was a backward compatible change for all C-based API use and for all Fortran-based API use.

HOWEVER, if a code used both the C API and the Fortran API, there was a breakage. If the Fortran API opens or creates the file, then it specifies that 8-byte integers will be passed through the API. Now, all C APIs also have to follow this convention which requires modification to existing code that worked prior to the 8-byte integer support. Another issue is that if the file is opened by the C API, it will by default expect 4-byte integers through the API. When a Fortran function is called, it will pass 8-byte integers and cause file corruption.

I hadn’t really thought about this use case, so the backward incompatibility issue wasn’t documented or even realized until now. I apologize for the lack of notice for this, but hopefully now that this is known it will be relatively straightforward to solve. Let me know if I can be of any help.

Basically, if your fortran application is passing 4-byte integers through the fortran API, then you need to link with the libexoIIv2for32.a library. If you are either using 8-byte integers explicitly, or are using a compiler flag (e.g., for gfortran -fdefault-real-8 -fdefault-integer-8), then you need to link with libexodus_for.a

Let me know if this helps or if there are still issues…

..Greg