[MITgcm-support] MNC oddities on Cray T3E
Mark Hadfield
m.hadfield at niwa.co.nz
Tue Mar 27 01:22:39 EDT 2007
Having just spent a couple of happy (?!) days getting the MNC package
working on our Cray T3E, I thought I should report my success to the
mailing list. Furthermore, my solution is a bit clunky at the moment and
I'd appreciate suggestions for doing things better.
The biggest difficulty relates to the compiler's idiosyncratic handling
of floating-point number precision. By default, single-precision real
numbers use 8 bytes (64 bits), as do double-precision real numbers, that is
REAL = DOUBLE = REAL*8
The compiler also supports a 4-byte floating-point type via a REAL*4
declaration; it does not have a REAL*16 type.
The compiler accepts a "-s default32" switch (which I didn't know about
until today) that "Adjusts the default sizes as follows: real, integer,
and logical are set to 32 bits; complex and double precision are set to
64 bits; double complex is set to 128 bits." Using this switch might
solve the problems I'll describe below, but would bring in the
complication that other libraries (notably the netCDF library) have been
built without it. So I'll leave that for another day.
The first problem I ran into was that the function MNCCDIR is
unavailable, because genmake2 found that linking with C routines was
broken and so disabled it. I worked around this by commenting out the
call. I suspect that the C-linking problem arises from type mismatches
between C and Fortran, but haven't got around to checking this out yet.
The second problem occurrs in subroutine MNC_CW_RL_W_OFFSET, defined in
pkg/mnc/MNC_CW_READWRITE_RL.F. When the model writes out information to
the state file, it crashes with a floating point exception when writing
out u-velocity data. The problem arises because the corresponding
variable (U) in the netCDF file has the FLOAT data type. In this
situation, MNC_CW_RL_W_OFFSET copies the data into a REAL*4 array,
resh_r, then puts the data with the netCDF library's NF_PUT_VARA_REAL
function. But NF_PUT_VARA_REAL expects the data to be of type REAL,
which on this platform is REAL*8, so it reads data from beyond the area
that's been initialised, leading to general mayhem.
My work-around is to declare resh_r as
#ifdef TARGET_T3E
REAL resh_r( MNC_MAX_BUFF )
#else
REAL*4 resh_r( MNC_MAX_BUFF )
#endif
This fixes things nicely. So I'm happy for the time being, but I wonder
if this problem can be solved more elegantly. Furthermore, I'm a bit
puzzled about the approach taken by MNC_CW_RL_W_OFFSET. The heart of the
subroutine is as follows
IF (stype(1:1) .EQ. 'D') THEN
...
err = NF_PUT_VARA_DOUBLE(fid, idv, vstart, vcount, resh_d)
ELSEIF (stype(1:1) .EQ. 'R') THEN
...
err = NF_PUT_VARA_REAL(fid, idv, vstart, vcount, resh_r)
ELSEIF (stype(1:1) .EQ. 'I') THEN
...
err = NF_PUT_VARA_INT(fid, idv, vstart, vcount, resh_i)
ENDIF
where resh_d is REAL*8, resh_r is REAL*4 and resh_i is INTEGER. So the
code goes to the trouble of creating and populating a data array that
matches the netCDF variable. But this is unnecessary, surely, as the
netCDF library will do this for us, see
http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-f77/Type-Conversion.html#Type-Conversion
--
Mark Hadfield "Ka puwaha te tai nei, Hoea tahi tatou"
m.hadfield at niwa.co.nz
National Institute for Water and Atmospheric Research (NIWA)
More information about the MITgcm-support
mailing list