MODULE M3UTILIOdoes the "proper F90 way" of encapsulating the Models-3 I/O API parameter, data structure, and function-declarations, in a way that nested Fortran
USE <module>constructs do not interact with older Fortran
INCLUDEstatements to generate multiple-declaration errors at compile time.
The issue is that when one has two or more Fortran-90
MODULE B, where both of these need access to facilities provded by the standard I/O API
IODECL3.EXT, there is a problem: if
INCLUDEs these, it introduces an artificial dependency of
MODULE B: where should the
INCLUDEstatements be placed (if they appear in both
MODULEs, the compiler will complain that variables and functions have repeated declarations, which is illegal. The problem is even worse if
USEs a third
MODULE C, independent of
B, that also needs I/O API
INCLUDEfiles: one can't necessarily make
C USE B, or vice versa.
However, the Fortran-90
USEconstruct does not have this problem:
Ccan all have statements
USE M3UTILIOwithout 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 M3UTILIOinto existing codes, one must not only remove all of the
INCLUDEstatements associated with the standard I/O API
IODECL3.EXT, one must also remove any (now extra, duplicate) declarations and
EXTERNALstatements for I/O API functions that now have explicit
MODULE 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 M3UTILIOitself includes, and therefore
USE M3UTILIOreplaces the
INCLUDEstatements for the following Models-3 I/O API
INCLUDEfiles:It further provides Fortran-90 style
INTERFACEblocks 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 the
BUFFERargument for WRITE3() does not have a single specified type; it may be
INTEGER, REAL, DOUBLE PRECISION, or
INTEGER*8 (M3INT, M3REAL, M3DBLE,, or
M3INT8, respectively) and may have an arbitrary number of dimensions, instead of being restricted (as an
INTERFACEwould require) to one single possibility like a 3-D
REAL BUFFER(:,:,:), or requiring over three thousand lines of "wrapper" code to support the implied polymorphism. (
IODECL3.EXTis invoked from this
MODULEto provide the
EXTERNALdeclarations for these F77-style routines, but not full interface blocks.)
It provides Fortran-90 "generic" (polymorphic)
INTERFACEs for a number of routines:
- 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.
- 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.
- Get a list of
CHARACTERstrings from the environment
- Get a single value of type
CHARACTERstrings from the environment, with default-value and optional
LOVAL, HIVALranges for the numeric-type versions.
INTEGER FUNCTION FINDKEY()
- Find a key-tuple of
REALs in a key-tuple table.
<type> FUNCTION GETVAL()
- Prompt for a numeric (
LOGICAL) value, with optional
LO, HIbounds or menu of
INTEGER FUNCTION LOCATE()
- Find the insertion-point fdor a key-tuple of
REALs in a key-tuple table (i.e., a table currently under construction).
- 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.
- Perform an indirect quicksort relative to a table of keytuples of
REALs (i.e., sort an index-table
INDX(1:N)so that the values
<table-variable>(INDX(1:N))are in sorted order).
- Construct 4-band interpolation matrix from
REAL*81-D (vector) or 2-D (gridded) locations to be used by
- Construct aan incidence matrix from
REAL*81-D (vector) or 2-D (gridded) locations, for use by
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, as well as SUBROUTINE LASTTIME() that robustly computes the last date&time in a time step sequence (even for millenia-long runs, without
Send comments to
Carlie J. Coats, Jr.