mpp_io_mod, is a set of simple calls for parallel I/O on distributed systems. It is geared toward the writing of data in netCDF format. It requires the modules and , upon which it is built.
type, public :: axistype
sequence
character(len=128) :: name
character(len=128) :: units
character(len=256) :: longname
character(len=8) :: cartesian
integer :: len
integer :: sense !+/-1, depth or height?
type(domain1D), pointer :: domain
real, dimension(:), pointer :: data
integer :: id, did
integer :: type ! external NetCDF type format for axis data
integer :: natt
type(atttype), pointer :: Att(:) ! axis attributes
end type axistype A field is described using the type fieldtype:
type, public :: fieldtype
sequence
character(len=128) :: name
character(len=128) :: units
character(len=256) :: longname
real :: min, max, missing, fill, scale, add
integer :: pack
type(axistype), dimension(:), pointer :: axes
integer, dimension(:), pointer :: size
integer :: time_axis_index
integer :: id
integer :: type ! external NetCDF format for field data
integer :: natt, ndim
type(atttype), pointer :: Att(:) ! field metadata
end type fieldtype An attribute (global, field or axis) is described using the atttype:
type, public :: atttype
sequence
integer :: type, len
character(len=128) :: name
character(len=256) :: catt
real(FLOAT_KIND), pointer :: fatt(:)
end type atttype
This default set of field attributes corresponds
closely to various conventions established for netCDF files. The pack attribute of a field defines whether or not a
field is to be packed on output. Allowed values of pack are 1,2,4 and 8. The value of pack is the number of variables written into 8
bytes. In typical use, we write 4-byte reals to netCDF output; thus
the default value of pack is 2. For pack = 4 or 8, packing uses a simple-minded linear
scaling scheme using the scale and add attributes. There is thus likely to be a significant loss of dynamic
range with packing. When a field is declared to be packed, the missing and fill attributes, if
supplied, are packed also.
...
type(domain2D), dimension(:), allocatable, target :: domain
type(fieldtype) :: field
type(axistype) :: x, y, z, t
...
call mpp_define_domains( (/1,nx,1,ny/), domain )
allocate( a(domain(pe)%x%data%start_index:domain(pe)%x%data%end_index, &
domain(pe)%y%data%start_index:domain(pe)%y%data%end_index,nz) )
...
call mpp_write_meta( unit, x, 'X', 'km', 'X distance', &
domain=domain(pe)%x, data=(/(float(i),i=1,nx)/) )
call mpp_write_meta( unit, y, 'Y', 'km', 'Y distance', &
domain=domain(pe)%y, data=(/(float(i),i=1,ny)/) )
call mpp_write_meta( unit, z, 'Z', 'km', 'Z distance', &
data=(/(float(i),i=1,nz)/) )
call mpp_write_meta( unit, t, 'Time', 'second', 'Time' )
call mpp_write_meta( unit, field, (/x,y,z,t/), 'a', '(m/s)', AAA', &
missing=-1e36 )
...
call mpp_write( unit, x )
call mpp_write( unit, y )
call mpp_write( unit, z )
... In this example, x and y have been
declared as distributed axes, since a domain decomposition has been
associated. z and t are undistributed
axes. t is known to be a record axis (netCDF
terminology) since we do not allocate the data element
of the axistype. Only one record axis may be
associated with a file. The call to initializes
the axes, and associates a unique variable ID with each axis. The call
to mpp_write_meta with argument field declared field to be a 4D variable that is a function
of (x,y,z,t), and a unique variable ID is associated
with it. A 3D field will be written at each call to mpp_write(field).
...
integer :: unit, natt, nvar, ntime
type(domain2D), dimension(:), allocatable, target :: domain
type(fieldtype), allocatable, dimension(:) :: fields
type(atttype), allocatable, dimension(:) :: global_atts
real, allocatable, dimension(:) :: times
...
call mpp_define_domains( (/1,nx,1,ny/), domain )
call mpp_read_meta(unit)
call mpp_get_info(unit,natt,nvar,ntime)
allocate(global_atts(natt))
call mpp_get_atts(unit,global_atts)
allocate(fields(nvar))
call mpp_get_vars(unit, fields)
allocate(times(ntime))
call mpp_get_times(unit, times)
allocate( a(domain(pe)%x%data%start_index:domain(pe)%x%data%end_index, &
domain(pe)%y%data%start_index:domain(pe)%y%data%end_index,nz) )
...
do i=1, nvar
if (fields(i)%name == 'a') call mpp_read(unit,fields(i),domain(pe), a,
tindex)
enddo
... In this example, the data are distributed as in the previous
example. The call to initializes
all of the metadata associated with the file, including global
attributes, variable attributes and non-record dimension data. The
call to mpp_get_info returns the number of global
attributes (natt), variables (nvar) and
time levels (ntime) associated with the file
identified by a unique ID (unit). mpp_get_atts returns all global attributes for
the file in the derived type atttype(natt). mpp_get_vars returns variable types
(fieldtype(nvar)). Since the record dimension data are not allocated for calls to , a separate call to mpp_get_times is required to access record dimension data. Subsequent calls to mpp_read return the field data arrays corresponding to
the fieldtype. The domain type is an optional
argument. If domain is omitted, the incoming field
array should be dimensioned for the global domain, otherwise, the
field data is assigned to the computational domain of a local array.
mpp_mod
mpp_domains_mod
use mpp_io_mod [, only: mpp_write_meta,
mpp_write,
mpp_read,
mpp_get_atts,
mpp_io_init,
mpp_io_exit,
mpp_open,
mpp_close,
mpp_read_meta,
mpp_get_info,
mpp_get_times,
mpp_flush,
mpp_get_ncid ]
call mpp_write_meta ( unit, axis, name, units, longname, cartesian, sense, domain, data )
call mpp_write_meta ( unit, field, axes, name, units, longname, min, max, missing, fill, scale, add, pack )
call mpp_write_meta ( unit, id, name, rval=rval, pack=pack )
call mpp_write_meta ( unit, id, name, ival=ival )
call mpp_write_meta ( unit, id, name, cval=cval )
call mpp_write_meta ( unit, name, rval=rval, pack=pack )
call mpp_write_meta ( unit, name, ival=ival )
call mpp_write_meta ( unit, name, cval=cval )
| unit | |
| name | |
| units | |
| longname | |
| cartesian | |
| sense | |
| domain | |
| data | |
| min, max | |
| missing | |
| fill | |
| scale | |
| add | |
| pack | |
| id | |
| cval | |
| ival | |
| rval |
| axis | |
| field |
mpp_write ( unit, axis )
mpp_write ( unit, field, data, tstamp )
mpp_write ( unit, field, domain, data, tstamp )
| tstamp | tstamp is an optional argument. It is to be omitted if the field was defined not to be a function of time. Results are unpredictable if the argument is supplied for a time- independent field, or omitted for a time-dependent field. Repeated writes of a time-independent field are also not recommended. One time level of one field is written per call. tstamp must be an 8-byte real, even if the default real type is 4-byte. |
data = packed_data*scale + addNOTE: mpp_write does not check to see if the scaled data in fact fits into the dynamic range implied by the specified packing. It is incumbent on the user to supply correct scaling attributes.
call mpp_read ( unit, field, data, time_index )
call mpp_read ( unit, field, domain, data, time_index )
| unit |
[integer] |
| field |
[type(fieldtype)] |
| domain | |
| time_index | time_index is an optional argument. It is to be omitted if the field was defined not to be a function of time. Results are unpredictable if the argument is supplied for a time- independent field, or omitted for a time-dependent field. |
| data |
[real, dimension(:,:,:)] |
call mpp_get_atts ( unit, global_atts)
| unit |
[integer] |
| global_atts |
[atttype, dimension(:)] |
call mpp_io_init ( flags, maxunit )
| flags |
[integer] |
| maxunit |
[integer] |
call mpp_io_exit ()
call mpp_open ( unit, file, action, form, access, threading, fileset, iospec, nohdrs, recl, pelist )
| file | file is the filename: REQUIRED
we append .nc to filename if it is a netCDF file
we append .<pppp> to filename if fileset is private (pppp is PE number) [character(len=*)] |
| action | action is one of MPP_RDONLY, MPP_APPEND, MPP_WRONLY or MPP_OVERWR. [integer] |
| form | form is one of MPP_ASCII: formatted read/write
MPP_NATIVE: unformatted read/write with no conversion
MPP_IEEE32: unformatted read/write with conversion to IEEE32
MPP_NETCDF: unformatted read/write with conversion to netCDF [integer] |
| access | access is one of MPP_SEQUENTIAL or MPP_DIRECT (ignored for netCDF).
RECL argument is REQUIRED for direct access IO. [integer] |
| threading | threading is one of MPP_SINGLE or MPP_MULTI
single-threaded IO in a multi-PE run is done by PE0. [integer] |
| fileset | fileset is one of MPP_MULTI and MPP_SINGLE
fileset is only used for multi-threaded I/O
if all I/O PEs in <pelist> use a single fileset, they write to the same file
if all I/O PEs in <pelist> use a multi fileset, they each write an independent file [integer] |
| pelist | pelist is the list of I/O PEs (currently ALL). [integer] |
| recl | recl is the record length in bytes. [integer] |
| iospec | iospec is a system hint for I/O organization, e.g assign(1) on SGI/Cray systems. [character(len=*)] |
| nohdrs | nohdrs has no effect when action=MPP_RDONLY|MPP_APPEND or when form=MPP_NETCDF [logical] |
| unit | unit is intent(OUT): always _returned_by_ mpp_open(). [integer] |
namelist / nml / ...
...
call mpp_open( unit, 'input.nml', action=MPP_RDONLY )
read(unit,nml) will result in each PE independently reading the same namelist.
call mpp_open( unit, ... iospec='-F cachea' )on an SGI/Cray system, which would pass the supplied iospec to the assign(3F) system call.
call mpp_close ( unit, action )
| unit |
[integer] |
| action |
[integer] |
call mpp_read_meta (unit)
| unit |
[integer] |
call mpp_get_info ( unit, ndim, nvar, natt, ntime )
| unit |
[integer] |
| ndim |
[integer] |
| nvar |
[integer] |
| natt |
[integer] |
| ntime |
[integer] |
call mpp_get_times ( unit, time_values )
| unit |
[integer] |
| time_values |
[real(DOUBLE_KIND), dimension(:)] |
call mpp_flush (unit)
| unit |
[integer] |
mpp_get_ncid (unit)
| unit |
[integer] |
use mpp_io_modIf netCDF output is desired, the cpp flag -Duse_netCDF must be turned on. The loader step requires an explicit link to the netCDF library (typically something like -L/usr/local/lib -lnetcdf, depending on the path to the netCDF library). netCDF release 3 for fortran is required.
The source consists of the main source file and also requires the following include files: (when compiled with ) GFDL users can check it out of the main CVS repository as part of the CVS module. The current public tag is . External users can download the latest package . Public access to the GFDL CVS repository will soon be made available.