MODULE M3UTILIO Fortran-90 styleMODULE M3UTILIOdoes 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 FortranINCLUDEstatements to generate multiple-declaration errors at compile time.The issue is that when one has two or more Fortran-90
MODULEs, sayMODULE AthatUSEsMODULE B, where both of these need access to facilities provded by the standard I/O APIINCLUDEfilesPARMS3.EXT,FDESC3.EXT, and/orIODECL3.EXT, there is a problem: ifMODULE BINCLUDEs these, it introduces an artificial dependency ofMODULE AuponMODULE B: where should theINCLUDEstatements be placed (if they appear in bothMODULEs, the compiler will complain that variables and functions have repeated declarations, which is illegal. The problem is even worse ifMODULE AUSEs a thirdMODULE C, independent ofB, that also needs I/O APIINCLUDEfiles: one can't necessarily makeC USE B, or vice versa.However, the Fortran-90
USEconstruct does not have this problem:MODULEsA,B, andCcan all have statementsUSE 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 theINCLUDEstatements associated with the standard I/O APIPARMS3.EXT,FDESC3.EXT, and/orIODECL3.EXT, one must also remove any (now extra, duplicate) declarations andEXTERNALstatements for I/O API functions that now have explicitINTERFACEs 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 M3UTILIOMODULE M3UTILIOitself includes, and thereforeUSE M3UTILIOreplaces theINCLUDEstatements for the following Models-3 I/O APIINCLUDEfiles:It further provides Fortran-90 style
PARMS3.EXTFDESC3.EXTIODECL3.EXTINTERFACEblocks 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 theBUFFERargument 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 anINTERFACEwould 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.EXTis invoked from thisMODULEto provide theEXTERNALdeclarations for these F77-style routines, but not full interface blocks.)It provides Fortran-90 "generic" (polymorphic)
INTERFACEs 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
INTEGERs,REALs, orCHARACTERstrings from the environment
SUBROUTINE ENVGET()
- Get a single value of type
INTEGERs,LOGICALs,REALs,REAL*8s, orCHARACTERstrings from the environment, with default-value and optionalLOVAL, HIVALranges for the numeric-type versions.
INTEGER FUNCTION FINDKEY()
- Find a key-tuple of
CHARACTERstrings,INTEGERs,INTEGER*8s, orREALs in a key-tuple table.
<type> FUNCTION GETVAL()
- Prompt for a numeric (
INTEGER,REAL,DOUBLE, orLOGICAL) value, with optionalLO, HIbounds or menu ofCHOICES, andDEFAULTresponse.
INTEGER FUNCTION LOCATE()
- Find the insertion-point fdor a key-tuple of
CHARACTERstrings,INTEGERs,INTEGER*8s, orREALs 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
CHARACTERstrings,INTEGERs,INTEGER*8s, orREALs (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
REALorREAL*81-D (vector) or 2-D (gridded) locations to be used bySUBROUTINE BILIN()orSUBROUTINE BMATVEC()(above).
SUBROUTINE UNGRIDI()
- Construct aan incidence matrix from
REALorREAL*81-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, as well as SUBROUTINE LASTTIME() that robustly computes the last date&time in a time step sequence (even for millenia-long runs, without
INTEGERoverflow).
Send comments to
Carlie J. Coats, Jr.
carlie@jyarborough.com