MODULE M3UTILIO
Fortran-90 styleMODULE M3UTILIO
does the "proper F90 way" of encapsulating the Models-3 I/O API parameter, data structure, and function-declarations, in a way that nested FortranUSE <module>
constructs do not interact with older FortranINCLUDE
statements to generate multiple-declaration errors at compile time.The issue is that when one has two or more Fortran-90
MODULE
s, sayMODULE A
thatUSE
sMODULE B
, where both of these need access to facilities provded by the standard I/O APIINCLUDE
filesPARMS3.EXT
,FDESC3.EXT
, and/orIODECL3.EXT
, there is a problem: ifMODULE B
INCLUDE
s these, it introduces an artificial dependency ofMODULE A
uponMODULE B
: where should theINCLUDE
statements be placed (if they appear in bothMODULE
s, the compiler will complain that variables and functions have repeated declarations, which is illegal. The problem is even worse ifMODULE A
USE
s a thirdMODULE C
, independent ofB
, that also needs I/O APIINCLUDE
files: one can't necessarily makeC USE B
, or vice versa.However, the Fortran-90
USE
construct does not have this problem:MODULE
sA
,B
, andC
can all have statementsUSE M3UTILIO
without causing multiple-declaration problems: the recognition that these statements provide one common set of declarations is now built into the Fortran-90 (and later) language, in a way not possible at all for Fortran-77 (and that must be managed manually by the programmer with #ifdefs for the corresponding C #include construct).Note that to retro-fit
MODULE M3UTILIO
into existing codes, one must not only remove all of theINCLUDE
statements associated with the standard I/O APIPARMS3.EXT
,FDESC3.EXT
, and/orIODECL3.EXT
, one must also remove any (now extra, duplicate) declarations andEXTERNAL
statements for I/O API functions that now have explicitINTERFACE
s inMODULE M3UTILIO
(the list being basically the full set of public I/O API functions). (If you get a "duplicate definition" compile-error, you probably missed one ;-( )
MODULE M3UTILIO
MODULE M3UTILIO
itself includes, and thereforeUSE M3UTILIO
replaces theINCLUDE
statements for the following Models-3 I/O APIINCLUDE
files:It further provides Fortran-90 style
PARMS3.EXT
FDESC3.EXT
IODECL3.EXT
INTERFACE
blocks for, basically, all of the public routines in the I/O API whose usage does not require F77 / "void pointer" arguments—for example, note that theBUFFER
argument for WRITE3() does not have a single specified type; it may beINTEGER, REAL, DOUBLE PRECISION
, orINTEGER*8 (M3INT, M3REAL, M3DBLE,
, orM3INT8
, respectively) and may have an arbitrary number of dimensions, instead of being restricted (as anINTERFACE
would require) to one single possibility like a 3-DREAL BUFFER(:,:,:)
, or requiring over three thousand lines of "wrapper" code to support the implied polymorphism. (IODECL3.EXT
is invoked from thisMODULE
to provide theEXTERNAL
declarations for these F77-style routines, but not full interface blocks.)It provides Fortran-90 "generic" (polymorphic)
INTERFACE
s for a number of routines:
SUBROUTINE BILIN()
- Use 4-band interpolation matrix from
SUBROUTINE UNGRIDB()
(below) to do bilinear interpolation from 2-D or 3-D gridded data to vector, layered-vector, 2D grid or 3D grid locations.
SUBROUTINE BMATVEC()
- Use 4-band interpolation matrix from
SUBROUTINE UNGRIDB()
to do bilinear interpolation-and-transpose from 2-D or 3-D gridded data to vector, layered-vector, 2D grid or 3D grid locations.
SUBROUTINE ENVLIST()
- Get a list of
INTEGER
s,REAL
s, orCHARACTER
strings from the environment
SUBROUTINE ENVGET()
- Get a single value of type
INTEGER
s,LOGICAL
s,REAL
s,REAL*8
s, orCHARACTER
strings from the environment, with default-value and optionalLOVAL, HIVAL
ranges for the numeric-type versions.
INTEGER FUNCTION FINDKEY()
- Find a key-tuple of
CHARACTER
strings,INTEGER
s,INTEGER*8
s, orREAL
s in a key-tuple table.
<type> FUNCTION GETVAL()
- Prompt for a numeric (
INTEGER
,REAL
,DOUBLE
, orLOGICAL
) value, with optionalLO, HI
bounds or menu ofCHOICES
, andDEFAULT
response.
INTEGER FUNCTION LOCATE()
- Find the insertion-point fdor a key-tuple of
CHARACTER
strings,INTEGER
s,INTEGER*8
s, orREAL
s in a key-tuple table (i.e., a table currently under construction).
SUBROUTINE PMATVEC()
- Aply an incidence matrix from
SUBROUTINE UNGRIDI()
(below) to do mapping from 1-D or 2-D input data arrays to 1-D or 2-D output arrays.
SUBROUTINE SORTI()
- Perform an indirect quicksort relative to a table of keytuples of
CHARACTER
strings,INTEGER
s,INTEGER*8
s, orREAL
s (i.e., sort an index-tableINDX(1:N)
so that the values<table-variable>(INDX(1:N))
are in sorted order).
SUBROUTINE UNGRIDB()
- Construct 4-band interpolation matrix from
REAL
orREAL*8
1-D (vector) or 2-D (gridded) locations to be used bySUBROUTINE BILIN()
orSUBROUTINE BMATVEC()
(above).
SUBROUTINE UNGRIDI()
- Construct aan incidence matrix from
REAL
orREAL*8
1-D (vector) or 2-D (gridded) locations, for use bySUBROUTINE PMATVEC()
.It also provides four cleanly-coded public parsing-utility routines SUBROUTINE FIXFIELD(), FUNCTION KEYVAL(), and SUBROUTINE KEYSTR() that replace various less-well-conceived SMOKE 1.x library-routines; SUBROUTINE FIXNULLS() that replaces trailing ASCII-nulls with blanks (to deal with problems caused by the lack of sophistication of netCDF's Fortran bindings), especially for MPAS-format netCDEF; as well as SUBROUTINE LASTTIME() that robustly computes the last date&time in a time step sequence (even for millenia-long runs, without
INTEGER
overflow).
Send comments to
Carlie J. Coats, Jr.
carlie@jyarborough.com