The ESMF utilities are a set of tools for quickly assembling modeling applications.
The ESMF Attribute class enables models to be self-describing via metadata, which are instances of Attribute name-value pairs.
The Time Management Library provides utilities for time and time interval representation and calculation, and higher-level utilities that control model time stepping, via clocks, as well as alarming.
The ESMF Config class provides configuration management based on NASA DAO's Inpak package, a collection of methods for accessing files containing input parameters stored in an ASCII format.
The ESMF LogErr class consists of a variety of methods for writing error, warning, and informational messages to log files. A default Log is created during ESMF initialization. Other Logs can be created later in the code by the user.
The DELayout class provides a layer of abstraction on top of the Virtual Machine (VM) layer. DELayout does this by introducing DEs (Decomposition Elements) as logical resource units. The DELayout object keeps track of the relationship between its DEs and the resources of the associated VM object. A DELayout can be shaped by the user at creation time to best match the computational problem or other design criteria.
The ESMF VM (Virtual Machine) class is a generic representation of hardware and system software resources. There is exactly one VM object per ESMF Component, providing the execution environment for the Component code. The VM class handles all resource management tasks for the Component class and provides a description of the underlying configuration of the compute resources used by a Component. In addition to resource description and management, the VM class offers the lowest level of ESMF communication methods.
The ESMF Fortran I/O utilities provide portable methods to access capabilities which are often implemented in different ways amongst different environments. Currently, two utility methods are implemented: one to find an unopened unit number, and one to flush an I/O buffer.
The ESMF Attribute class is a metadata utility that supports emerging standards in a flexible way. The Attribute class is useful for documenting data provenance and encourages models to be more self describing. Attributes can also be used to automate some aspects of model execution and coupling.
Metadata, which is data about data, is broken down into name-value pairs by the Attribute class. Attributes can be attached at any level of the ESMF object hierarchy, and in some cases the Attributes of different ESMF objects can be linked together to form a corresponding Attribute hierarchy. Attribute hierarchies are linked up automatically for the most part, with the exception of links between Components and between a Component and a State. Attribute hierarchies can also be unlinked, copied, and moved around as needed.
ESMF Attribute packages are used to aggregate, store, and output model metadata. They can be nested inside each other to make larger organized packages, distributed across processors and updated at runtime, and expanded to suit specific needs. The ESMF-supplied Attribute packages are designed around accepted metadata conventions, such as: climate and forecast (CF) [7], ISO standards [3], and the METAFOR Common Information Model (CIM) [5] [4].
Most of the ESMF deep objects can host Attributes, and every object that can hold individual Attributes can also hold Attribute packages. Attribute hierarchies are supported for a majority of the Attribute bearing classes. More information on the various Attribute capabilities, and the classes for which they are supported appear in the following sections.
Reading Attribute XML files requires the Xerces C++ library, v3.1.0 or better. For more details, see the "ESMF Users Guide", "Building and Installing the ESMF, Third Party Libraries, Xerces". Writing Attribute XML files is performed with the standard C++ output file stream facility.
There are two pieces to the information stored in Attributes. One piece is the property name and type, and its relation to other properties; this is the schema. The other piece is the range of values that are valid for a particular property; this is the controlled vocabulary. For many information models, including the Common Information Model (CIM), these two pieces are managed and versioned separately.
ESMF implements the appropriate schema internally; it translates the Attributes as specified in the Attribute packages into the correct format based on the convention and purpose as specified in arguments to most Attribute functions. The controlled vocabularies, or Attribute values, however, are not controlled or validated within ESMF.
The CIM is a formal model of the climate modeling process being developed by the European Union's METAFOR project. The Earth System - Documentation (ES-DOC) project is an evolution of the METAFOR project, and they provide a detailed description of the CIM here.
ESMF is currently implementing only a subset of version 1.5 of the CIM, though this representation is expected to grow.
Mapping Attributes to the CIM
The ESMF Attribute packages provide a structure for the Attributes that are useful for climate modelers. When the ESMF_AttributeWrite() function is called with "CIM" XML specified as the target, ESMF translates these package structures into a format defined by the CIM schema. The package descriptions in the following sections provide a mapping from the ESMF Attribute name to the CIM schema field.
For example, in the CIM Main Attribute Package, the Attribute named "LongName" is mapped to the CIM schema field, "software:SoftwareComponent:longName":
Name | Definition | Controlled Vocabulary | CIM Schema Field (<CIM section>:<Entity>:<Field>) |
LongName | A version of the component name with all acronyms spelled out. | N/A | software:SoftwareComponent:longName |
There are 3 parts to this mapping:
The CIM section refers to the categories, or subsections, of the CIM mentioned above. In this example, the CIM section is "software". To find this section in the CIM schema repository, go to the CIM repository and then select the "software" drop down (see Figure 27 ).
You can view the schema graphically in a UML diagram by selecting the software.png file and then visually search the picture for the SoftwareComponent entity.
However, this view does not provide field details, such as type and description. Alternatively, you can select the software.xsd file, and then search the XML for the entity, "SoftwareComponent," and the field, "longName," which will provide the details for this field (see Figure 28 ).
As the ES-DOC team continues its work, more tools will be provided to support CIM implementations. Currently, a more user-friendly way to view the CIM schema is available here.
ESMF's approach to Attributes can be summarized as follows:
Of the ESMF objects with Attributes, only some can link their Attributes together in an Attribute hierarchy. These objects are:
Every ESMF deep object is given a root Attribute on creation. These root Attributes serve as the attachment point for all metadata that is stored on a particular ESMF object, including all Attributes and Attribute packages. The root Attributes can also be connected together via the ESMF_AttributeLink() functionality. This happens automatically in most cases, such as when a Field is added to a FieldBundle, and results in the formation of an Attribute hierarchy which mirrors the structure of the underlying object hierarchy.
When two Attribute hierarchies are linked together the objects are given read-only access to each other's Attributes. To ensure consistency across a distributed system, there can only ever be one set of Attributes associated with each ESMF object. This implies that a copy operation on an ESMF object Attribute hierarchy can use a value copy for all Attributes which are owned by the object being copied, but must use a reference copy for all Attributes which the object can access (through links) but does NOT own. See section 36.9.6 for more details on this concept.
The most common use for this hierarchy capability is for linking the Attributes of a Field to the FieldBundle which holds it, which is then linked to the State that is used to transport all of the data for a Component. All of these links, with the exception of the link between the Component and the State, are automatically handled by ESMF. Additionally, the State will automatically set a VariableIntent Attribute for Field when that Field is added to the State. VariableIntent will be set to either Export or Import.
At this time, all ESMF objects which are enabled to contain Attributes can also contain Attribute packages, which are groupings of individual Attributes. Every Attribute package is specified by a convention and a purpose, such as "CF" and "General" (see below), as arguments to many of the Attribute functions. These are used to validate ESMF Attribute packages against existing metadata conventions. The user can choose to use an ESMF pre-defined Attribute package, specify their own Attribute package, or add customized Attributes to any of the ESMF pre-defined Attribute packages. Currently, the creation and setting of Attribute packages is quite involved, but future development with IO will allow for a more automated approach to populating Attribute packages from a file. This is already possible via ESMF_AttributeRead() for the ESMF/CF Attribute packages supplied by ESMF, as well as for custom individual Attributes not in a package.
The standard Attribute packages supplied by ESMF exist for the following ESMF objects:
The packages described in this section are grouped by the ESMF object they apply to. The creation of custom attributes and custom attribute packages is also possible and is discussed in Section 36.2.7. In some cases it is possible to nest custom packages on top of ESMF packages. Attribute package nesting is described separately in Section 36.3.
Some Attributes come with a controlled vocabulary. A controlled vocabulary is a list of options that can be selected as the value of the attribute. The controlled vocabularies listed in this documentation represent those chosen by the community. They are not exhaustive and users may set these Attributes to a different value if they so choose. The primary consequence of doing so is that the resulting output may not be recognized by any of the online tools being developed with respect to this controlled vocabulary.
There are many attributes that are used to describe components. There are currently 4 predefined component-level Attribute packages, with sub-packages defined for the 2nd:
1. Earth System Grid (ESG) Basic Attribute Package
Name | Definition | Controlled Vocabulary |
Agency | An administrative unit of government. | DoD, DOE, DOI, NASA, NOAA, NSF |
Author | The person who created the content of a book, article, or other source. | N/A |
CodingLanguage | The computer language in which a unit of software is written. | C, C++, F77, F90, Java |
ComponentLongName | The name of a model, model component, simulation, experiment, or dataset with all acronyms spelled out. | N/A |
ComponentShortName | A version of the component name that contains acronyms. | N/A |
Discipline | A subject, theme, category, or general area of interest. | Aerosol, Fisheries, Climate, Carbon Cycle, Hydrology, Land, Ocean, Polar, Sediment, Storm Surge, Turbulence, Weather, Wave, Weather Prediction |
Institution | An organization associated with a model component, simulation, or dataset. | N/A |
ModelComponentFramework | The software package or mechanism used to transfer and transform data between model components. | CCA, ESMF, Flume, FMS, OASIS, SWMF |
PhysicalDomain | A description of the geographic range being simulated. | Atmosphere, Earth System, Ice, Lake, Land Ocean, River |
Version | A specific form or variation of an artifact, i.e. a unit of software or metadata. | N/A |
2. Common Information Model (CIM) Main Attribute Package
Name | Definition | Controlled Vocabulary | CIM Schema Field (<CIM section>:<Entity>:<Field>) |
Description | A multi-line description of the component. | N/A | software:SoftwareComponent:description |
LongName | A version of the component name with all acronyms spelled out. | N/A | software:SoftwareComponent:longName |
MetadataVersion*** | The version number of the simulation metadata. | N/A | software:modelComponent:metadataVersion |
ModelType* | A short string describing the discipline of a model component. | Advection, Aerosol3D-Sources etc. | software:ModelComponent:type |
PreviousVersion** | Name of the previous version of a model or model component. | N/A | shared:Reference:name |
PreviousVersionDescription** | A short note about the previous version of the model or model component. | N/A | shared:Relationship:description |
ReleaseDate | The date a model component was issued. | N/A | software:SoftwareComponent:releaseDate |
ShortName* | A version of the component name that contains acronyms. | N/A | software:SoftwareComponent:shortName |
SimulationDuration | The length of time a simulation runs. | N/A | activity:SimulationRun:dateRange |
SimulationEndDate | The date in simulated time of the end of a model simulation. | N/A | activity:SimulationRun:dateRange |
SimulationEnsembleID | The reference name or number of the ensemble to which a simulation belongs. | N/A | activity:EnsembleMember:ensembleMemberID |
SimulationLongName | The name of the simulation with any acronyms spelled out. | N/A | activity:NumericalActivity:longName |
SimulationNumberOfProcessingElements | The number of PEs used in the simulation. | N/A | software:Parallelization:processes |
SimulationProjectName | A campaign, such as a model intercomparison project, that may involve multiple groups and experiments. | N/A | activity:Activity:project |
SimulationRationale | The reason for performing a simulation. | N/A | activity:Activity:rationale |
SimulationShortName | The name of the simulation. | N/A | activity:NumericalActivity:shortName |
SimulationStartDate* | The date in simulated time of the start of a model simulation. | N/A | activity:SimulationRun:dateRange |
URL | A URL associated with a model component. | N/A | shared:CI_OnlineResource:linkage |
Version | Version number of the component. | N/A | appended to software:SoftwareComponent:shortName |
2.1. CIM Platform Attribute Package
Name | Definition | Controlled Vocabulary | CIM Schema Field (<CIM section>:<Entity>:<Field>) |
CompilerName** | The brand of the software that takes source code and turns it into an executable. | Absoft, Default, Intel, Lahey, NAG, Pathscale, PGI, PGIGCC, XLF, XLFGCC | shared:Compiler:compilerName |
CompilerVersion** | The specific configuration value of the software used to take source code and turn it into executable code. | N/A | shared:Compiler:compilerVersion |
MachineCoresPerProcessor | The number of sub-divided elements or mini-chips on a computer chip. | N/A | shared:Machine:machineCoresPerProcessor |
MachineDescription | A short note about the machine. | N/A | shared:Machine:machineDescription |
MachineInterconnectType | The technology used to associate each node in a supercomputer with every other node. | Cray Interconnect, Fat Tree, Gigabit Ethernet, Infiniband, Mixed, Myrinet, Numalink, Quadrics, SP Switch | shared:Machine:machineInterconnect |
MachineMaximumProcessors | The highest number of computer chips on a computer system. | N/A | shared:Machine:machineMaximumProcessors |
MachineName* | The name given to a computer by its system administrators. This is not the brand name of the system. | N/A | shared:Machine:machineName |
MachineOperatingSystem | The software that is responsible for the management and coordination of activities and the sharing of resources of a computer. | Aix, Darwin, Irix64, Linux, SUNOS, Unicos | shared:Machine:machineOperatingSystem |
MachineProcessorType | The type of computer chip used in a particular computer platform. | Altix, AMD x86-64, Bluegene, G4, G5, Intel EM64T, Intel IA-64, Itanium, NEC, Opteron, Origin3800, Pentium 3, Pentium 4, SP, SPARC, X1, Xeon, XT3-4, ZX6000 | shared:Machine:machineProcessorType |
MachineSystem | The type of computer system (e.g. vector, parallel, cluster, etc.). | Beowulf, Parallel, Vector | shared:Machine:machineSystem |
MachineVendor | The brand name of a computer system. | ACS, Action, Appro International, Bull SA, Cray Inc, Dalco AG Switzerland, Dawning, Dell, Fujitsu, Hitachi, HP, IBM, Intel, Koi Computers, Lenovo, Mac, NEC, NEC SUN, NUDT, PC, Pyramid Computer, Raytheon-Aspen Systems, Self Made, SGI, Sun Microsystems, T-platforms | shared:Machine:machineVendor |
2.2. ISO Responsible Party Attribute Package
Name | Definition | Controlled Vocabulary | CIM Schema Field (<CIM section>:<Entity>:<Field>) |
Abbreviation | The abbreviation of an individual or organization associated with a model component or simulation. | N/A | shared:ResponsibleParty:abbreviation |
EmailAddress | The email address that others can use to ask questions about a model component. | N/A | shared:CI_Address:electronicMailAddress |
Name | The name of an author, contact, funder, centre, or principal investigator. | N/A | shared:CI_ResponsibleParty:individualName, shared:CI_ResponsibleParty:organisationName, shared:CI_ResponsibleParty:positionName (depending on NameType value) |
NameType | The type of entity that Name references. | Individual, Organization, Position | Not part of CIM; used to determine which CIM field to use for Name |
PhysicalAddress | The address of the person designated to provide information about a model component. | N/A | shared:CI_Address:deliveryPoint |
ResponsiblePartyRole* | A flag to define the role of the Responsible Party. | Author, PI, Contact, Center, Funder | shared:CI_ResponsibleParty:role |
URL | A URL of an individual or organization. | N/A | shared:CI_OnlineResource:linkage |
2.3. ISO Citation Attribute Package
Name | Definition | Controlled Vocabulary | CIM Schema Field (<CIM section>:<Entity>:<Field>) |
Date* | The date of the citation. | N/A | shared:CI_Citation:Date |
DOI | The assigned Digital Object Identifier (DOI) of the citation. | N/A | shared:CI_Citation:otherCitationDetails |
LongTitle | The text of the citation or pointer (e.g. URL) that further describes a model component or simulation. | N/A | shared:CI_Citation:collectiveTitle |
PresentationForm | A description of the type of citation. | documentDigital, documentHardcopy, imageDigital, imageHardcopy, mapDigital, mapHardcopy, modelDigital, modelHardcopy, profileDigital, profileHardcopy, tableDigital, tableHardcopy, videoDigital, videoHardcopy | shared:CI_Citation:presentationForm |
ShortTitle* | An abbreviation for the citation. This could be the short scientific citation (e.g. Murphy, 2009) or the title of a web page. | N/A | shared:CI_Citation:title |
URL | Website associated with the citation. | N/A | appended to shared:CI_Citation:collectiveTitle |
3. Common Information Model (CIM) Scientific Properties Package
The AtmosAdvection Component has a scientific property named: TracersSchemeName AtmosAdvection is a sub-component of the AtmosDynamicalCore component, which is a sub-component of Atmosphere. Therefore, the name to use for this Scientific Property is: AtmosphereAtmosDynamicalCoreAdmosAdvectionTracersSchemeName.
Name | Definition | Controlled Vocabulary | CIM Schema Field (<CIM section>:<Entity>:<Field>) |
<Scientific property name> | <METAFOR definition>. | Spreadsheet containing CVs. | software:SoftwareComponent:scientificProperties |
4. Common Information Model (CIM) Component Properties Package
Name | Definition | Controlled Vocabulary | CIM Schema Field (<CIM section>:<Entity>:<Field>) |
<User-defined name> | <User-defined definition>. | N/A | software:SoftwareComponent:componentProperties |
There is currently only 1 predefined State-level Attribute package:
1. ESMF Basic State Attribute Package
Name | Definition | Controlled Vocabulary |
Intent | An indication of whether a state is imported into or exported from a particular model component. This refers to coupling, and not history output. | Export,Import |
Several standards exist to describe fields. There are currently 4 predefined Field-level Attribute packages:
1. Common Information Model (CIM) Inputs
Name | Definition | Controlled Vocabulary | CIM Schema Field (<CIM section>:<Entity>:<Field>) |
CouplingPurpose* | The form of the input condition (e.g. initial condition or boundary condition). | Ancillary, Boundary, Initial | software:Coupling:purpose |
CouplingSource* | The component the input condition is coming from. | N/A | software:Coupling:couplingSource |
CouplingTarget* | The component the input condition is going to. | N/A | software:Coupling:couplingTarget |
Description | A multi-line description of the input. | N/A | software:Coupling:description |
Frequency | The frequency (e.g. 2 months or 5 days) that a field from one component is input to another. | n Seconds, n Minutes, n Hours, n Days, n Months, n Years, n Decades, n Centuries | software:Timing:rate |
SpatialRegriddingMethod | Method used to interpolate a field from one grid (source grid) to another (target grid). | Linear, Near-Neighbor, Cubic, Conservative-First-Order, Conservative-Second-Order, Conservative, Non-Conservative | software:SpatialRegridding:spatialRegriddingStandardMethod |
SpatialRegriddingDimension | Dimension of the regridding method. | 1D, 2D, 3D | software:SpatialRegridding:spatialRegriddingDimension |
Technique | The software package or mechanism used to transfer and transform data between model components. | CCSM Flux Coupler, ESMF, Files, FMS, MCT, OASIS3, Shared | N/A |
TimeTransformationType | Temporal transformation performed on the input field before or after regridding onto the target grid. | Exact, None, Time Accumulation, Time Average, Time Interpolation | software:TimeTransformation:mappingType |
2. Earth System Grid (ESG) Field
Name | Definition | Controlled Vocabulary |
Intent | An indication of whether a variable is exported or imported. This refers to coupling and not history output. | Export,Import |
3. Climate Forecast (CF) Convention Extended
Name | Definition | Controlled Vocabulary |
StandardName | The approved CF standard name for a variable if it exists. | N/A |
4. Climate Forecast (CF) Convention General
Name | Definition | Controlled Vocabulary |
LongName | An ad-hoc long descriptive name which may, for example, be used for labeling plots | N/A |
ShortName* | The short_name is technically not part of the CF standard but is commonly the name of the variable on the output file and so is distinct from the long_name | N/A |
Units | The value of the units attribute is a string that can be recognized by UNIDATA's Udunits package | N/A |
At this time the Array packages are the same as the Field packages.
There are 2 grid attribute packages in ESMF.
1. Gridspec
Name | Definition | Controlled Vocabulary |
CongruentTiles | Indicates whether or not all the tiles contained within a grid mosaic are of the same size and shape. | True, False |
DimensionOrder | The order in which latitude and longitude appear within the two dimensional grid array. | N/A |
DiscretizationType | Specifies the method by which a two-dimensional coordinate system is sampled to form a computational grid. | Logically rectangular, Pixel-based catchment, Structured triangular, Unstructured triangular |
GeometryType | Indicates the geometric figure used to approximate the shape of the Earth, e.g. "sphere". | Ellipsoid, Plane, Sphere |
GridType | A text description of the grid that uses common terminology. | Gnomonic, Cubed Sphere, Displaced Pole, Icosahedral geodesic, Reduced gaussian, Regular lat lon, Spectral gaussian, Tripolar, Yin Yang |
HorizontalResolution | The number of points within the horizontal domain of a model or grid. | N/A |
IsConformal | Indicates if the grid tile is angle-preserving. If so, angles measured on the grid are equal to the equivalent angles on the Earth. | True, False |
IsRegular | Indicates whether or not the horizontal coordinates of the grid can be defined using 1D arrays (vectors). This means that grid node locations are defined by the cartesian product of the X/Lon and Y/Lat coordinate vectors. It also means that grid cells are logically rectangular (they may also be physically rectangular in the case of projected coordinates). | True, False |
IsUniform | Indicates whether or not the horizontal coordinates of a grid have fixed offsets in the X and Y directions. If the offset is the same in both directions then the grid is logically square, otherwise it is logically rectangular. | True, False |
NorthPoleLocation | Defines the lat-long position of the 'north pole' used by the grid tile in the case of rotated/displaced pole grids. | N/A |
NumberOfCells | The number of cells in an unstructured grid. | N/A |
NumberOfGridTiles | The number of tiles in a mosaic. | N/A |
NX | Specifies the length of the X, or longitude, dimension of the grid tile. | N/A |
NY | Specifies the length of the Y, or latitude, dimension of the grid tile. | N/A |
2. ESMF Grid
Name | Definition | Controlled Vocabulary |
RegDecompX | The number of DEs in X a particular grid is decomposed into. | N/A |
RegDecompY | The number of DEs in Y a particular grid is decomposed into. | N/A |
The following is an alphabetical list of all the attributes implemented in ESMF, their definitions, and which packages they are contained within.
Name | Definition | Attribute Package |
Agency | An administrative unit of government. | ESG Basic Component |
CodingLanguage | The computer language in which a unit of software is written. | ESG Basic Component |
CompilerName | The brand of the software that takes source code and turns it into an executable. | CIM Platform |
CompilerVersion | The specific configuration value of the software used to take source code and turn it into executable code. | CIM Platform |
CouplingPurpose | The form of the input condition (e.g. initial condition or boundary condition). | CIM Inputs |
CouplingSource | The component the input condition is coming from. | CIM Inputs |
CouplingTarget | The component the input condition is going to. | CIM Inputs |
Description | A multi-line description of a component or input. | CIM Main, CIM Inputs |
Date | The date of the citation. | ISO Citation |
DimensionOrder | The order in which latitude and longitude appear within the two dimensional grid array. | Gridspec |
DiscretizationType | Specifies the method by which a two-dimensional coordinate system is sampled to form a computational grid. | Gridspec |
DOI | The assigned Digital Object Identifier (DOI) of the citation. | ISO Citation |
EmailAddress | The email address that others can use to ask questions about a model component. | ISO Responsible Party |
Frequency | The frequency (e.g. months, days) that a field from one component is input to another. | CIM Inputs |
FullName | The name of a model, model component, simulation, experiment, or dataset with all acronyms spelled out. | ESG Basic Component |
GeometryType | Indicates the geometric figure used to approximate the shape of the Earth, e.g. "sphere". | Gridspec |
GridType | A text description of the grid that uses common terminology. | Gridspec |
IsConformal | Indicates if the grid tile is angle-preserving. If so, angles measured on the grid are equal to the equivalent angles on the Earth. | Gridspec |
IsRegular | Indicates whether or not the horizontal coordinates of the grid can be defined using 1D arrays (vectors). This means that grid node locations are defined by the cartesian product of the X/Lon and Y/Lat coordinate vectors. It also means that grid cells are logically rectangular (they may also be physically rectangular in the case of projected coordinates). | Gridspec |
Institution | An organization associated with a model component, simulation, or dataset. | ESG Basic Component |
Intent | An indication of whether a field or state is imported into or exported from a particular model component. This refers to coupling, and not history output. | ESMF State, ESMF Field |
IsUniform | Indicates whether or not the horizontal coordinates of a grid have fixed offsets in the X and Y directions. If the offset is the same in both directions then the grid is logically square, otherwise it is logically rectangular. | Gridspec |
LongName | The name of an object with all acronyms spelled out. For fields, it is an ad-hoc long descriptive name which may, for example, be used for labeling plots. | CIM Main, CF General |
LongTitle | The text of the citation or pointer (e.g. URL) that further describes a model component or simulation. | ISO Citation |
MachineCoresPerProcessor | The number of sub-divided elements or mini-chips on a computer chip. | CIM Platform |
MachineDescription | A short note about the machine. | CIM Platform |
MachineInterconnectType | The technology used to associate each node in a supercomputer with every other node. | CIM Platform |
MachineMaximumProcessors | The highest number of computer chips on a computer system. | CIM Platform |
MachineName | The name given to a computer by its system administrators. This is not the brand name of the system. | CIM Platform |
MachineOperatingSystem | The software that is responsible for the management and coordination of activities and the sharing of resources of a computer. | CIM Platform |
MachineProcessorType | The type of computer chip used in a particular computer platform. | CIM Platform |
MachineSystem | The type of computer system (e.g. vector, parallel, cluster, etc.). | CIM Platform |
MachineVendor | The brand name of a computer system. | CIM Platform |
MetadataVersion | The version number of the simulation metadata. | CIM Main |
ModelComponentFramework | The software package or mechanism used to transfer and transform data between model components. | ESG Basic Component |
ModelType | A short string describing the discipline of a model component. | CIM Main |
Name | The name of an author, contact, funder, centre, or principal investigator. | ISO Responsible Party |
NameType | The type of entity that Name references. | ISO Responsible Party |
NorthPoleLocation | Defines the lat-long position of the 'north pole' used by the grid tile in the case of rotated/displaced pole grids. | Gridspec |
NumberOfCells | The number of cells in an unstructured grid. | Gridspec |
NX | Specifies the length of the X, or longitude, dimension of the grid tile. | Gridspec |
NY | Specifies the length of the Y, or latitude, dimension of the grid tile. | Gridspec |
PhysicalAddress | The address of the person designated to provide information about a model component. | ISO Responsible Party |
PhysicalDomain | A description of the geographic range being simulated. | ESG Basic Component |
PresentationForm | A description of the type of citation. | ISO Citation |
PreviousVersion | Name of the previous version of a model or model component. | CIM Main |
PreviousVersionDescription | A short note about the previous version of the model or model component. | CIM Main |
ReleaseDate | The year a model component was issued. | CIM Main |
RegDecompX | The number of DEs in X a particular grid is decomposed into. | ESMF Grid |
RegDecompY | The number of DEs in Y a particular grid is decomposed into. | ESMF Grid |
ResponsiblePartyRole | A flag to define the role of the Responsible Party. | ISO Responsible Party |
ShortName | For component: a version of the component name that contains acronyms. For field: The short_name is technically not part of the CF standard but is commonly the name of the variable on the output file and so is distinct from the long_name. | CIM Main, CF General |
ShortTitle | An abbreviation for the citation. This could be the short scientific citation (e.g. Murphy, 2009) or the title of a web page. | ISO Citation |
SimulationDuration | The length of time a simulation runs. | CIM Main |
SimulationEndDate | The date in simulated time of the end of a model simulation. | CIM Main |
SimulationEnsembleID | The reference name or number of the ensemble to which a simulation belongs. | CIM Main |
SimulationLongName | The name of the simulation with any acronyms spelled out. | CIM Main |
SimulationNumberOfProcessingElements | The number of PEs used in the simulation. | CIM Main |
SimulationProjectName | A campaign, such as a model intercomparison project, that may involve multiple groups and experiments. | CIM Main |
SimulationRationale | The reason for performing a simulation. | CIM Main |
SimulationStartDate | The date in simulated time of the start of a model simulation. | CIM Main |
SimulationShortName | The name of the simulation. | CIM Main |
SpatialRegriddingMethod | Method used to interpolate a field from one grid (source grid) to another (target grid). | CIM Inputs |
SpatialRegriddingDimension | Dimension of the regridding method. | CIM Inputs |
StandardName | The approved CF standard name for a variable if it exists. | CF Extended |
TimeTransformationType | Temporal transformation performed on the input field before or after regridding onto the target grid. | CIM Inputs |
Technique | The software package or mechanism used to transfer and transform data between model components. | CIM Inputs |
URL | URL of the object being described. Exists in multple packages. | CIM Main, ISO Responsible Party, ISO Citation |
Units | The value of the units attribute is a string that can be recognized by UNIDATA's Udunits package. | CF General |
Version | A specific form or variation of an artifact i.e. a unit of software or metadata. | CIM Main, ESG Basic Component |
ESMF allows for the creation of custom attribute packages, each of which has a user-defined convention and purpose, as well as a set of user-defined attributes. This can be done to augment one of the pre-defined packages (via package nesting 36.3) or to create a suite of attributes unique to the user. A custom attribute package currently outputs only in simple XML format, when used as a stand-alone package (not when used to augment a pre-defined package). Examples of how to create such custom packages are contained in Sections 36.7.2 and 36.7.3.
Nesting is a way of creating larger Attribute packages out of smaller ones and allows users to add the attributes they want to an existing package. It is very useful when combining a custom package with a pre-defined package. One or more child Attribute packages can be nested within a parent package, and this can be repeated multiple times, allowing a full Attribute tree (hierarchical) structure to be created. Breaking Attributes up into smaller packages that are then nested also allows for the construction of complex attribute trees where certain structures repeat themselves, allowing for Attribute package reusability.
Several of the ESMF pre-defined packages, when added to an ESMF object, are created with nested packages:
CIM Main - Component package - is a nest with three child packages:
CIM Inputs - Field package - is a nest with one child package:
ESG (or ESMF) General - Field package - is a nest with one child package:
CF Extended - Field package - is a nest with one child package:
ESMF General - Grid package - is a nest with one child package:
An explanation of the Attribute packages convention and purpose is in order at this point. The purpose specifier is really just meant as an additional means, beyond the use of "convention", to specify Attribute packages. One could imagine that the CF convention would want to be able to have Attribute packages divided up in some fashion, which ESMF could then keep track of with the purpose specifier. It was added with the intention of allowing Attributes, and packages, maximum flexibility. Take the Field's ESMF standard Attribute package for example. This package is made up of three nested Attribute packages. The lowest one is made up of three Attributes with convention=CF and purpose=General. The next level contains one Attribute with convention=CF but purpose=Extended. On top of this is the convention=ESG package, also with purpose=General.
The ESMF_AttributeWrite() interface is used to write the contents of an Attribute package to a file. This routine can be called on any ESMF object that is capable of holding Attribute packages. It can also write out all Attributes in Attribute packages with the same convention and purpose throughout an entire ESMF object hierarchy.
There are three primary ways of exporting Attributes:
The flag that is used in the ESMF_AttributeWrite() interface to determine which format for writing the Attribute packages is called the ESMF_AttWriteFlag, with values as described below. The resulting file will be placed in the execution directory after it is written and closed.
When ESMF_AttWriteFlag is set to ESMF_ATTWRITE_TAB (the default), a tab-delimited ascii file containing name-value pairs of attributes in the packages will be written. The file will be named for the name of the ESMF object from which ESMF_AttributeWrite() is called. The suffix will be .stdout.
When ESMF_AttWriteFlag is set to ESMF_ATTWRITE_XML, an XML file containing name-value pairs of attributes in the packages will be written. The file will be named for the name of the ESMF object from which ESMF_AttributeWrite() is called. The suffix will be .xml.
When the ESMF object from which ESMF_AttributeWrite() is called is a Component, and the Attribute package convention="CIM", and the purpose="Model Component Simulation Description", and ESMF_AttWriteFlag is set to ESMF_ATTWRITE_XML, an XML file conforming to the CIM standard will be written. The file will contain Attributes from the entire Component tree and their contained Fields. The file will be named for the name of the ESMF Component object from which ESMF_AttributeWrite() is called, and the suffix will be .xml.
There is a deviation from the standard CIM in the ESMF code: if the top-level object is not a component, or the proper convention ("CIM") or purpose ("Model Component Simulation Description") are not used, then the simple XML logic will be followed, and elements such as, "variable_set" and "variable" may be found in the exported XML.
Internal ESMF class information can be retrieved through the Attribute class with the ESMF_AttributeGet() interface. The Grid class is the prototype for this capability. Internal information is retrieved by specifying the name in ESMF_AttributeGet() as the keyword of the desired argument from one of the ESMF_GridGet()interfaces. The 'value' of the Attribute must be of the corresponding type that is required to retrieve the desired piece of information. There are a few pieces of information that cannot be retrieved from the Grid through the Attribute interface at this time, see Tables 5 - 7 to determine what is currently available.
The name of an Attribute that represents internal class information must have 'ESMF:' prepended. This is to indicate that the information should be retrieved directly from class methods. The input arguments must not have the 'ESMF:' string prepended, and they should be specified as a character string with the name and value separated by a colon. For example, the localDe=0 would be specified like this: 'localDe:0'.
Note: Attribute access to internal class information does not have the normal Attribute restriction that the values of the Attributes must be consistent across the current VM.
There is an example of how to use this capability in Section 36.7.5.
The name, type, input arguments and original Grid interface for each of the pieces of internal Grid information that can be retrieved through the Attribute class are listed in Tables 5 - 7. The name of the Attribute is specified by the character strings in the first column, and the type of the output is specified in the second column. The third column specifies which input information is required (or optional) to retrieve the information and the fourth column gives a link to a detailed description of the input arguments.
Note: The following pieces of Grid information cannot be retrieved with this method: distgrid, coordDimMap, arbIndexList, and coord.
Name | Type | Input arguments | Original Interface |
arbDim | integer | ESMF_GridGet() | |
arbDimCount | integer | ESMF_GridGet() | |
arbIndexCount | integer | localDe | ESMF_GridGet() |
computationalCount | integer(:) | staggerloc, localDe | ESMF_GridGet() |
computationalLBound | integer(:) | staggerloc, localDe | ESMF_GridGet() |
computationalUBound | integer(:) | staggerloc, localDe | ESMF_GridGet() |
coordDimCount | integer(:) | ESMF_GridGet() | |
coordTypeKind | ESMF_TypeKind_Flag | ESMF_GridGet() | |
dimCount | integer | ESMF_GridGet() | |
distgridToGridMap | integer(:) | ESMF_GridGet() | |
exclusiveCount | integer(:) | staggerloc, localDe | ESMF_GridGet() |
exclusiveLBound | integer(:) | staggerloc, localDe | ESMF_GridGet() |
exclusiveUBound | integer(:) | staggerloc, localDe | ESMF_GridGet() |
gridEdgeLWidth | integer(:) | ESMF_GridGet() | |
gridEdgeUWidth | integer(:) | ESMF_GridGet() | |
gridAlign | integer(:) | ESMF_GridGet() | |
indexflag | ESMF_Index_Flag | ESMF_GridGet() | |
isLBound | logical | localDe | ESMF_GridGet() |
isUBound | logical | localDe | ESMF_GridGet() |
localDECount | integer | ESMF_GridGet() | |
maxIndex | integer(:) | tile, staggerloc | ESMF_GridGet() |
minIndex | integer(:) | tile, staggerloc | ESMF_GridGet() |
name | character | ESMF_GridGet() | |
rank | integer | ESMF_GridGet() | |
staggerlocCount | integer | ESMF_GridGet() | |
status | ESMF_GridStatus_Flag | ESMF_GridGet() | |
tileCount | integer | ESMF_GridGet() |
Name | Type | Input arguments | Original Interface |
computationalCount | integer(:) | coordDim, (optional) staggerloc, (optional) localDe | ESMF_GridGetCoord() |
computationalLBound | integer(:) | coordDim, (optional) staggerloc, (optional) localDe | ESMF_GridGetCoord() |
computationalUBound | integer(:) | coordDim, (optional) staggerloc, (optional) localDe | ESMF_GridGetCoord() |
exclusiveCount | integer(:) | coordDim, (optional) staggerloc, (optional) localDe | ESMF_GridGetCoord() |
exclusiveLBound | integer(:) | coordDim, (optional) staggerloc, (optional) localDe | ESMF_GridGetCoord() |
exclusiveUBound | integer(:) | coordDim, (optional) staggerloc, (optional) localDe | ESMF_GridGetCoord() |
totalCount | integer(:) | coordDim, (optional) staggerloc, (optional) localDe | ESMF_GridGetCoord() |
totalLBound | integer(:) | coordDim, (optional) staggerloc, (optional) localDe | ESMF_GridGetCoord() |
totalUBound | integer(:) | coordDim, (optional) staggerloc, (optional) localDe | ESMF_GridGetCoord() |
Name | Type | Input arguments | Original Interface |
computationalCount | integer(:) | itemflag, (optional) staggerloc, (optional) localDe | ESMF_GridGetItem() |
computationalLBound | integer(:) | itemflag, (optional) staggerloc, (optional) localDe | ESMF_GridGetItem() |
computationalUBound | integer(:) | itemflag, (optional) staggerloc, (optional) localDe | ESMF_GridGetItem() |
exclusiveCount | integer(:) | itemflag, (optional) staggerloc, (optional) localDe | ESMF_GridGetItem() |
exclusiveLBound | integer(:) | itemflag, (optional) staggerloc, (optional) localDe | ESMF_GridGetItem() |
exclusiveUBound | integer(:) | itemflag, (optional) staggerloc, (optional) localDe | ESMF_GridGetItem() |
totalCount | integer(:) | itemflag, (optional) staggerloc, (optional) localDe | ESMF_GridGetItem() |
totalLBound | integer(:) | itemflag, (optional) staggerloc, (optional) localDe | ESMF_GridGetItem() |
totalUBound | integer(:) | itemflag, (optional) staggerloc, (optional) localDe | ESMF_GridGetItem() |
DESCRIPTION:
Indicates which type of Attribute object count to return.
The type of this flag is:
type(ESMF_AttGetCountFlag)
The valid values are:
DESCRIPTION:
Indicates whether or not to descend the Attribute hierarchy for the present operation.
The type of this flag is:
type(ESMF_AttTreeFlag)
The valid values are:
DESCRIPTION:
Indicates which file format to use in the write operation.
The type of this flag is:
type(ESMF_AttWriteFlag)
The valid values are:
This section describes the use of the Attribute class. There are eight examples that follow, which outline the use of Attributes at three increasing levels of difficulty. The first example covers basic Attribute manipulations on the gridded Component. The second example covers the Attribute package capabilities, including Attribute package nesting and Attribute hierarchy linking. The third example covers Attribute management in a distributed environment and the I/O utilities. These examples will be best understood if followed in an ascending order from basic to advanced. The fourth example shows how to use the CIM Attribute packages. The last four examples cover setting of Attribute packages and custom Attributes from an XML file.
This example illustrates the most basic usage of the Attribute class. This demonstration of Attribute manipulation is limited to the gridded Component, but the same principles apply to the coupler Component, State, Grid, FieldBundle, Field, ArrayBundle and Array. The functionality that is demonstrated includes setting and getting Attributes, working with Attributes with different types and lists, removing Attributes, and getting default Attributes. Various other uses of ESMF_AttributeGet() is covered in detail in the last section. The first thing we must do is declare variables and initialize ESMF.
! Use ESMF framework module use ESMF use ESMF_TestMod implicit none ! Local variables integer :: rc, finalrc, petCount, localPet, & itemCount, count, result type(ESMF_VM) :: vm type(ESMF_GridComp) :: gridcomp character(ESMF_MAXSTR) :: name type(ESMF_TypeKind_Flag) :: tk integer(ESMF_KIND_I4) :: inI4 integer(ESMF_KIND_I4), dimension(3) :: inI4l integer(ESMF_KIND_I8) :: inI8 integer(ESMF_KIND_I8), dimension(3) :: inI8l real(ESMF_KIND_I4) :: inR4 real(ESMF_KIND_I4), dimension(3) :: inR4l real(ESMF_KIND_I8) :: inR8 real(ESMF_KIND_I8), dimension(3) :: inR8l character(ESMF_MAXSTR) :: inChar character(ESMF_MAXSTR), dimension(3) :: inCharl, & defaultCharl, dfltoutCharl character(ESMF_MAXSTR), dimension(8) :: outCharl logical :: inLog logical, dimension(3) :: inLogl, value character(ESMF_MAXSTR) :: testname character(ESMF_MAXSTR) :: failMsg
! initialize ESMF finalrc = ESMF_SUCCESS call ESMF_Initialize(vm=vm, defaultlogfilename="AttributeEx.Log", & logkindflag=ESMF_LOGKIND_MULTI, rc=rc)
! get the vm call ESMF_VMGet(vm, petCount=petCount, localPet=localPet, rc=rc)
We will construct the gridded Component which will be responsible for all of the Attributes we will be manipulating.
if (petCount<4) then gridcomp = ESMF_GridCompCreate(name="gridcomp", & petList=(/0/), rc=rc) else gridcomp = ESMF_GridCompCreate(name="gridcomp", & petList=(/0,1,2,3/), rc=rc) endif
We can set Attributes using the ESMF_AttributeSet() command. Attributes can be any of several different types, all of which are demonstrated here.
inI4 = 4 inI4l = (/1,2,3/) inI8 = 4 inI8l = (/1,2,3/) inR4 = 4 inR4l = (/1,2,3/) inR8 = 4 inR8l = (/1,2,3/) inChar = "Character string 4" inCharl = (/ "Character string 1", & "Character string 2", & "Character string 3" /) inLog = .true. inLogl = (/.true., .false., .true. /) call ESMF_AttributeSet(gridcomp, name="ESMF_I4name", value=inI4, rc=rc)
call ESMF_AttributeSet(gridcomp, name="ESMF_I4namelist", & valueList=inI4l, rc=rc)
call ESMF_AttributeSet(gridcomp, name="ESMF_I8name", value=inI8, rc=rc)
call ESMF_AttributeSet(gridcomp, name="ESMF_I8namelist", & valueList=inI8l, rc=rc)
call ESMF_AttributeSet(gridcomp, name="ESMF_R4name", value=inR4, rc=rc)
call ESMF_AttributeSet(gridcomp, name="ESMF_R4namelist", & valueList=inR4l, rc=rc)
call ESMF_AttributeSet(gridcomp, name="ESMF_R8name", value=inR8, rc=rc)
call ESMF_AttributeSet(gridcomp, name="ESMF_R8namelist", & valueList=inR8l, rc=rc)
call ESMF_AttributeSet(gridcomp, name="Character_name", & value=inChar, rc=rc)
call ESMF_AttributeSet(gridcomp, name="Character_namelist", & valueList=inCharl, rc=rc)
call ESMF_AttributeSet(gridcomp, name="Logical_name", value=inLog, rc=rc)
call ESMF_AttributeSet(gridcomp, name="Logical_namelist", & valueList=inLogl, rc=rc)
We can retrieve Attributes by issuing the ESMF_AttributeGet() command. This command can also be used with an optional default value (or value list) so that if the Attribute is not found a value is returned without an error code. Removal of Attributes is also possible, and is demonstrated here as well. One of the Attributes previously created will be retrieved, then removed, then retrieved again using a default return value. In order to use the default return value capabilites, we must first set up a default parameter.
defaultCharl = (/ "Character string 4", & "Character string 5", & "Character string 6" /) itemCount=3 call ESMF_AttributeGet(gridcomp, name="Character_namelist", & valueList=outCharl(1:5), itemCount=itemCount, rc=rc)
call ESMF_AttributeRemove(gridcomp, name="Character_namelist", rc=rc)
call ESMF_AttributeGet(gridcomp, name="Character_namelist", & valueList=dfltoutCharl, defaultvalueList=defaultCharl,rc=rc)
There are more overloaded instances of ESMF_AttributeGet() which allow the retrieval of Attribute information by name or index number, or a query for the count of the Attributes on a certain object. These capabilities are demonstrated here by first retrieving the name of an Attribute using the index number, keep in mind that these index numbers start from 1. Then the name that is retrieved is used to get other information about the Attribute, such as the typekind, and the number of items in the value of the Attribute. This information is then used to actually retreive the Attribute value. Then the count of the number of Attributes on the object will be retrieved.
call ESMF_AttributeGet(gridcomp, attributeIndex=11 , name=name, rc=rc)
call ESMF_AttributeGet(gridcomp, name=name, typekind=tk, & itemCount=itemCount, rc=rc)
if (tk==ESMF_TYPEKIND_Logical .AND. itemCount==3) then call ESMF_AttributeGet(gridcomp, name=name, valueList=value, rc=rc)
endif call ESMF_AttributeGet(gridcomp, count=count, rc=rc)
This example is slightly more complex than the example presented in section 36.7.1 and illustrates the use of the Attribute class to create Attribute hierarchies using Attribute packages. A gridded Component is used in conjunction with two States, a FieldBundle, and various realistic Fields to create an Attribute hierarchy and copy it from one State to another. Attribute packages are created on the Component and Fields, and the standard Attributes in each package are used in the Attribute hierarchy. The Attribute package nesting capability is demonstrated by nesting the standard ESMF supplied packages for the Fields inside a user specified Attribute package with a customized convention.
We must construct the ESMF objects that will be responsible for the Attributes we will be manipulating. These objects include the gridded Component, two States, a FieldBundle, and 10 Fields. In this trivial example we are constructing empty Fields with no underlying Grid.
if (petCount<4) then gridcomp = ESMF_GridCompCreate(name="gridded_comp_ex2", & petList=(/0/), rc=rc) else gridcomp = ESMF_GridCompCreate(name="gridded_comp_ex2", & petList=(/0,1,2,3/), rc=rc) endif
importState = ESMF_StateCreate(name="importState", & stateintent=ESMF_STATEINTENT_IMPORT, rc=rc)
exportState = ESMF_StateCreate(name="exportState", & stateintent=ESMF_STATEINTENT_EXPORT, rc=rc)
DPEDT = ESMF_FieldEmptyCreate(name='DPEDT', rc=rc)
DTDT = ESMF_FieldEmptyCreate(name='DTDT', rc=rc)
DUDT = ESMF_FieldEmptyCreate(name='DUDT', rc=rc)
DVDT = ESMF_FieldEmptyCreate(name='DVDT', rc=rc)
PHIS = ESMF_FieldEmptyCreate(name='PHIS', rc=rc)
QTR = ESMF_FieldEmptyCreate(name='QTR', rc=rc)
CNV = ESMF_FieldEmptyCreate(name='CNV', rc=rc)
CONVCPT = ESMF_FieldEmptyCreate(name='CONVCPT', rc=rc)
CONVKE = ESMF_FieldEmptyCreate(name='CONVKE', rc=rc)
CONVPHI = ESMF_FieldEmptyCreate(name='CONVPHI', rc=rc)
fbundle = ESMF_FieldBundleCreate(name="fbundle", rc=rc)
Now we can add Attribute packages to all of the appropriate objects. We will use the ESMF supplied Attribute packages for the Fields and the Component. On the Fields, we will first use ESMF_AttributeAdd() to create standard Attribute packages, then we will nest customized Attribute packages around the ESMF standard Attribute packages. In this simple example the purpose for the Attribute packages will be specified as "General" in all cases.
convESMF = 'ESMF' convCC = 'CustomConvention' purpGen = 'General' attrList(1) = 'Coordinates' attrList(2) = 'Mask' ! DPEDT call ESMF_AttributeAdd(DPEDT, convention=convESMF, purpose=purpGen, & rc=rc)
call ESMF_AttributeAdd(DPEDT, convention=convCC, purpose=purpGen, & attrList=attrList, nestConvention=convESMF, nestPurpose=purpGen, & rc=rc)
... and so on for the other 9 Fields.
The standard Attribute package currently supplied by ESMF for Field contains 6 Attributes, 2 of which are set automatically. The remaining 4 Attributes in the standard Field Attribute package must be set manually by the user. We must also set the Attributes of our own custom Attribute package, which is built around the ESMF standard Attribute package.
name1 = 'ShortName' name2 = 'StandardName' name3 = 'LongName' name4 = 'Units' ! DPEDT value1 = 'DPEDT' value2 = 'tendency_of_air_pressure' value3 = 'Edge pressure tendency' value4 = 'Pa s-1' ! Custom Attributes call ESMF_AttributeSet(DPEDT, name='Coordinates', value='latlon', & convention=convCC, purpose=purpGen, rc=rc)
call ESMF_AttributeSet(DPEDT, name='Mask', value='yes', & convention=convCC, purpose=purpGen, rc=rc)
! ESMF Attributes call ESMF_AttributeSet(DPEDT, name1, value1, convention=convESMF, & purpose=purpGen, rc=rc)
call ESMF_AttributeSet(DPEDT, name2, value2, convention=convESMF, & purpose=purpGen, rc=rc)
call ESMF_AttributeSet(DPEDT, name3, value3, convention=convESMF, & purpose=purpGen, rc=rc)
call ESMF_AttributeSet(DPEDT, name4, value4, convention=convESMF, & purpose=purpGen, rc=rc)
... and so on for the other 9 Fields.
The standard Attribute package currently supplied by ESMF for Component contains 10 Attributes. These Attributes conform to both the ESG and CF conventions, and must be set manually.
call ESMF_AttributeSet(gridcomp, 'Agency', 'NASA', & convention=convESMF, purpose=purpGen, rc=rc)
call ESMF_AttributeSet(gridcomp, 'Author', 'Max Suarez', & convention=convESMF, purpose=purpGen, rc=rc)
call ESMF_AttributeSet(gridcomp, 'CodingLanguage', & 'Fortran 90', convention=convESMF, purpose=purpGen, rc=rc)
call ESMF_AttributeSet(gridcomp, 'Discipline', & 'Atmosphere', convention=convESMF, purpose=purpGen, rc=rc)
call ESMF_AttributeSet(gridcomp, 'ComponentLongName', & 'Goddard Earth Observing System Version 5 Finite Volume Dynamical Core', & convention=convESMF, purpose=purpGen, rc=rc)
call ESMF_AttributeSet(gridcomp, 'ModelComponentFramework', & 'ESMF', convention=convESMF, purpose=purpGen, rc=rc)
call ESMF_AttributeSet(gridcomp, 'ComponentShortName', & 'GEOS-5 FV dynamical core', & convention=convESMF, purpose=purpGen, rc=rc)
call ESMF_AttributeSet(gridcomp, 'PhysicalDomain', & 'Earth system', convention=convESMF, purpose=purpGen, rc=rc)
call ESMF_AttributeSet(gridcomp, 'Version', & 'GEOSagcm-EROS-beta7p12', convention=convESMF, purpose=purpGen, rc=rc)
Adding the Fields to the FieldBundle will automatically ``link" the Attribute hierarchies. The same type of link will be generated when adding a FieldBundle to a State.
call ESMF_FieldBundleAdd(fbundle, (/DPEDT/), rc=rc)
call ESMF_FieldBundleAdd(fbundle, (/DTDT/), rc=rc)
call ESMF_FieldBundleAdd(fbundle, (/DUDT/), rc=rc)
call ESMF_FieldBundleAdd(fbundle, (/DVDT/), rc=rc)
call ESMF_FieldBundleAdd(fbundle, (/PHIS/), rc=rc)
call ESMF_FieldBundleAdd(fbundle, (/QTR/), rc=rc)
call ESMF_FieldBundleAdd(fbundle, (/CNV/), rc=rc)
call ESMF_FieldBundleAdd(fbundle, (/CONVCPT/), rc=rc)
call ESMF_FieldBundleAdd(fbundle, (/CONVKE/), rc=rc)
call ESMF_FieldBundleAdd(fbundle, (/CONVPHI/), rc=rc)
call ESMF_StateAdd(exportState, fieldbundleList=(/fbundle/), rc=rc)
The link between a State and the Component of interest must be set manually.
call ESMF_AttributeLink(gridcomp, exportState, rc=rc)
There are currently two different formats available for writing the contents of the Attribute packages in an Attribute hierarchy. There is an XML formatted write, which generates an .xml file in the execution directory with the contents of the write. There is also a tab-delimited write which writes to standard out, a file generated in the execution directory with the extension .stdout. Either of the ESMF_AttributeWrite() formats can be called on any of the objects which are capable of manipulating Attributes, but only from objects in an Attribute hierarchy which contain ESMF standard Attribute packages can it be confirmed that any relevant information be written. The ESMF_AttributeWrite() capability is only functional for single-item Attributes at this point, it will be more robust in future releases. A flag is used to specify which format to write, the default is tab-delimited.
call ESMF_AttributeWrite(gridcomp,convESMF,purpGen, & attwriteflag=ESMF_ATTWRITE_XML,rc=rc)
call ESMF_AttributeWrite(gridcomp,convESMF,purpGen,rc=rc)
This example illustrates how to create a user-defined, custom Attribute package. The package is created on a gridded Component with three custom Attributes.
We must construct the ESMF gridded Component object that will be responsible for the custom Attribute package we will be manipulating.
if (petCount<4) then gridcomp = ESMF_GridCompCreate(name="gridded_comp_ex3", & petList=(/0/), rc=rc) else gridcomp = ESMF_GridCompCreate(name="gridded_comp_ex3", & petList=(/0,1,2,3/), rc=rc) endif
Now we can add a custom Attribute package to the gridded Component object.
customConv = 'CustomConvention' customPurp = 'CustomPurpose' customAttrList(1) = 'CustomAttrName1' customAttrList(2) = 'CustomAttrName2' customAttrList(3) = 'CustomAttrName3' call ESMF_AttributeAdd(gridcomp, convention=customConv, & purpose=customPurp, attrList=customAttrList, rc=rc)
We must set the Attribute values of our custom Attribute package.
call ESMF_AttributeSet(gridcomp, 'CustomAttrName1', 'CustomAttrValue1', & convention=customConv, purpose=customPurp, rc=rc)
call ESMF_AttributeSet(gridcomp, 'CustomAttrName2', 'CustomAttrValue2', & convention=customConv, purpose=customPurp, rc=rc)
call ESMF_AttributeSet(gridcomp, 'CustomAttrName3', 'CustomAttrValue3', & convention=customConv, purpose=customPurp, rc=rc)
Write out the contents of our custom Attribute package to an XML file, which is generated with a .xml file extension in the execution directory.
call ESMF_AttributeWrite(gridcomp,customConv,customPurp, & attwriteflag=ESMF_ATTWRITE_XML,rc=rc)
This advanced example illustrates the proper methods of Attribute manipulation in a distributed environment to ensure consistency of metadata across the VM. This example is much more complicated than the previous two because we will be following the flow of control of a typical model run with two gridded Components and one coupling Component. We will start out in the application driver, declaring Components, States, and the routines used to initialize, run and finalize the user's model Components. Then we will follow the control flow into the actual Component level through initialize, run, and finalize examining how Attributes are used to organize the metadata.
This example follows a simple user model with two gridded Components and one coupling Component. The initialize routines are used to set up the application data and the run routines are used to manipulate the data. Accordingly, most of the Attribute manipulation will take place in the initialize phase of each of the three Components. The two gridded Components will be running on exclusive pieces of the VM and the coupler Component will encompass the entire VM so that it can handle the Attribute communications.
The control flow of this example will start in the application driver, after which it will complete three cycles through the three Components. The first cycle will be through the initialize routines, from the first gridded Component to the second gridded Component to the coupler Component. The second cycle will go through the run routines, from the first gridded Component to the coupler Component to the second Gridded component. The third cycle will be through the finalize routines in the same order as the first cycle.
In the application driver, we must now construct some ESMF objects, such as the gridded Components, the coupler Component, and the States. This is also where it is determined which subsets of the PETs of the VM the Components will be using to run their initialize, run, and finalize routines.
gridcomp1 = ESMF_GridCompCreate(name="gridcomp1", & petList=(/0,1/), rc=rc)
gridcomp2 = ESMF_GridCompCreate(name="gridcomp2", & petList=(/2,3/), rc=rc)
cplcomp = ESMF_CplCompCreate(name="cplcomp", & petList=(/0,1,2,3/), rc=rc)
c1exp = ESMF_StateCreate(name="Comp1 exportState", & stateintent=ESMF_STATEINTENT_EXPORT, rc=rc)
Before the individual components are initialized, run, and finalized Attributes should be set at the Component level. Here we are going to use the ESG Attribute package on the first gridded Component. The Attribute package is added, and then each of the Attributes is set. The Attribute hierarchy of the Component is then linked to the Attribute hierarchy of the export State in a manual fashion.
convESMF = 'ESMF' purpGen = 'General' call ESMF_AttributeAdd(gridcomp1, convention=convESMF, purpose=purpGen, & rc=rc)
call ESMF_AttributeSet(gridcomp1, 'Agency', 'NASA', & convention=convESMF, purpose=purpGen, rc=rc)
call ESMF_AttributeSet(gridcomp1, 'Author', 'Max Suarez', & convention=convESMF, purpose=purpGen, rc=rc)
call ESMF_AttributeSet(gridcomp1, 'CodingLanguage', & 'Fortran 90', convention=convESMF, purpose=purpGen, rc=rc)
call ESMF_AttributeSet(gridcomp1, 'Discipline', & 'Atmosphere', convention=convESMF, purpose=purpGen, rc=rc)
call ESMF_AttributeSet(gridcomp1, 'ComponentLongName', & 'Goddard Earth Observing System Version 5 Finite Volume Dynamical Core', & convention=convESMF, purpose=purpGen, rc=rc)
call ESMF_AttributeSet(gridcomp1, 'ModelComponentFramework', & 'ESMF', & convention=convESMF, purpose=purpGen, rc=rc)
call ESMF_AttributeSet(gridcomp1, 'ComponentShortName', & 'GEOS-5 FV dynamical core', convention=convESMF, purpose=purpGen, rc=rc)
call ESMF_AttributeSet(gridcomp1, 'PhysicalDomain', & 'Earth system', convention=convESMF, purpose=purpGen, rc=rc)
call ESMF_AttributeSet(gridcomp1, 'Version', & 'GEOSagcm-EROS-beta7p12', convention=convESMF, purpose=purpGen, rc=rc)
call ESMF_AttributeLink(gridcomp1, c1exp, rc=rc)
Now the individual Components will be run. First we will initialize the two gridded Components, then we will initialize the coupler Component. During each of these Component initialize routines Attribute packages will be added, and the Attributes set. The Attribute hierarchies will also be linked. As the gridded Components will be running on exclusive portions of the VM, the Attributes will need to be made available across the VM using an ESMF_StateReconcile() call in the coupler Component. The majority of the work with Attributes will take place in this portion of the model run, as metadata rarely needs to be changed during run time.
What follows are the calls from the driver code that run the initialize, run, and finalize routines for each of the Components. After these calls we will step through the first cycle as explained in the introduction, through the intialize routines of gridded Component 1 to gridded Component 2 to the coupler Component.
call ESMF_GridCompInitialize(gridcomp1, exportState=c1exp, rc=rc) call ESMF_GridCompInitialize(gridcomp2, importState=c2imp, rc=rc) call ESMF_CplCompInitialize(cplcomp, importState=c1exp, & exportState=c2imp, rc=rc)
call ESMF_GridCompRun(gridcomp1, exportState=c1exp, rc=rc)
call ESMF_CplCompRun(cplcomp, importState=c1exp, & exportState=c2imp, userRc=urc, rc=rc)
call ESMF_GridCompRun(gridcomp2, importState=c2imp, rc=rc)
call ESMF_GridCompFinalize(gridcomp1, exportState=c1exp, rc=rc)
call ESMF_GridCompFinalize(gridcomp2, importState=c2imp, rc=rc)
call ESMF_CplCompFinalize(cplcomp, importState=c1exp, & exportState=c2imp, rc=rc)
In the first gridded Component initialize routine we need to create some Attribute packages and set all of the Attributes. These Attributes will be attached to realistic Fields, containing a Grid, which are contained in a FieldBundle. The first thing to do is declare variables and make the Grid.
type(ESMF_VM) :: vm integer :: petCount, status, myPet character(ESMF_MAXSTR) :: name1,name2,name3,name4,value1,value2, & value3,value4,convESMF,purpGen,convCC type(ESMF_ArraySpec) :: arrayspec type(ESMF_Grid) :: grid type(ESMF_Field) :: DPEDT,DTDT,DUDT,DVDT,PHIS,QTR,CNV,CONVCPT, & CONVKE,CONVPHI type(ESMF_FieldBundle) :: fieldbundle character(ESMF_MAXSTR),dimension(2) :: attrList rc = ESMF_SUCCESS call ESMF_GridCompGet(comp, vm=vm, rc=status) call ESMF_VMGet(vm, petCount=petCount, localPet=myPet, rc=status) call ESMF_ArraySpecSet(arrayspec, typekind=ESMF_TYPEKIND_R8, rank=2, & rc=rc) grid = ESMF_GridCreateNoPeriDim(minIndex=(/1,1/), maxIndex=(/100,150/), & regDecomp=(/1,petCount/), & gridEdgeLWidth=(/0,0/), gridEdgeUWidth=(/0,0/), & indexflag=ESMF_INDEX_GLOBAL, rc=rc)
At this point the Fields will need to have Attribute packages attached to them, and the Attributes will be set with appropriate values.
convCC = 'CustomConvention' convESMF = 'ESMF' purpGen = 'General' name1 = 'ShortName' name2 = 'StandardName' name3 = 'LongName' name4 = 'Units' value1 = 'DPEDT' value2 = 'tendency_of_air_pressure' value3 = 'Edge pressure tendency' value4 = 'Pa s-1' DPEDT = ESMF_FieldCreate(grid, arrayspec=arrayspec, & staggerloc=ESMF_STAGGERLOC_CENTER, rc=status) call ESMF_AttributeAdd(DPEDT, convention=convESMF, purpose=purpGen, & rc=status) call ESMF_AttributeSet(DPEDT, name1, value1, convention=convESMF, & purpose=purpGen, rc=status) call ESMF_AttributeSet(DPEDT, name2, value2, convention=convESMF, & purpose=purpGen, rc=status) call ESMF_AttributeSet(DPEDT, name3, value3, convention=convESMF, & purpose=purpGen, rc=status) call ESMF_AttributeSet(DPEDT, name4, value4, convention=convESMF, & purpose=purpGen, rc=status)
... and so on for the other 9 Fields.
Now the Fields will be added to the FieldBundle, at which point the Attribute hierarchies of the Fields will also be attached to the Attribute hierarchy of the FieldBundle. After that, the FieldBundle will be attached to the export State, again at which time the Attribute hierarchy of the FieldBundle will be attached to the Attribute hierarchy of the export State.
fieldbundle = ESMF_FieldBundleCreate(name="fieldbundle", rc=status) call ESMF_FieldBundleSet(fieldbundle, grid=grid, rc=status) call ESMF_FieldBundleAdd(fieldbundle, (/DPEDT/), rc=status) call ESMF_FieldBundleAdd(fieldbundle, (/DTDT/), rc=status) call ESMF_FieldBundleAdd(fieldbundle, (/DUDT/), rc=status) call ESMF_FieldBundleAdd(fieldbundle, (/DVDT/), rc=status) call ESMF_FieldBundleAdd(fieldbundle, (/PHIS/), rc=status) call ESMF_FieldBundleAdd(fieldbundle, (/QTR/), rc=status) call ESMF_FieldBundleAdd(fieldbundle, (/CNV/), rc=status) call ESMF_FieldBundleAdd(fieldbundle, (/CONVCPT/), rc=status) call ESMF_FieldBundleAdd(fieldbundle, (/CONVKE/), rc=status) call ESMF_FieldBundleAdd(fieldbundle, (/CONVPHI/), rc=status) call ESMF_StateAdd(exportState, fieldbundleList=(/fieldbundle/), rc=status)
At this point, the driver of the model run will transfer control to the initialize phase of the second gridded Component.
In the second gridded Component initialize routine we don't have anything to do. The data that was created in the initialize routine of the first gridded Component will be passed to this Component through the coupler Component. The data will not be used in this Component until the run phase of the model. So now the application driver transfers control to the initialize phase of the coupler Component.
In the coupler Component initialize routine all that is required is to ensure consistent data across the VM. The data created in the first gridded Component on one set of the PETs in the VM is intended to be read and manipulated by the second gridded Component which runs on an exclusive set of the PETs of the VM for this application. We need to first make that data consistent across the entire VM with the ESMF_StateReconcile() call. This State level call handles both the data - Fields and FieldBundles, and the metadata - Attribute and Attribute packages. There is a flag in this call to allow the user to specify whether they want the metadata to be reconciled or not.
type(ESMF_VM) :: vm rc = ESMF_SUCCESS call ESMF_CplCompGet(comp, vm=vm, rc=rc) call ESMF_StateReconcile(importState, vm=vm, & attreconflag=ESMF_ATTRECONCILE_ON, rc=rc) call ESMF_StateReconcile(exportState, vm=vm, & attreconflag=ESMF_ATTRECONCILE_ON, rc=rc)
At this point, the driver of the model run will transfer control to the run phase of the first gridded Component.
In the run phase of the first gridded Component is typically where the data contained in the Fields is manipulated. For this simple example we will do no actual data manipulation because all we are interested in at this point is the metadata. What we will do is add a nested Attribute package inside the currently existing Attribute package on each Field. We will also change the value of one of the Attributes in the original Attribute package, and remove another of the Attributes from the original Attribute package on each of the Fields. The first thing is to declare variables and get the Component, VM, State, and FieldBundle.
type(ESMF_VM) :: vm integer :: petCount, status, myPet, k character(ESMF_MAXSTR) :: name2,value2,convESMF,purpGen,purp2,name3 character(ESMF_MAXSTR),dimension(2) :: attrList type(ESMF_Field) :: field type(ESMF_FieldBundle) :: fieldbundle type(ESMF_Grid) :: grid rc = ESMF_SUCCESS convESMF = 'ESMF' purpGen = 'General' name2 = 'StandardName' value2 = 'default_standard_name' name3 = 'LongName' purp2 = 'Extended' attrList(1) = 'Coordinates' attrList(2) = 'Mask' call ESMF_GridCompGet(comp, vm=vm, rc=status) call ESMF_VMGet(vm, petCount=petCount, localPet=myPet, rc=status) call ESMF_StateGet(exportState, "fieldbundle", fieldbundle, rc=rc) call ESMF_FieldBundleGet(fieldbundle, grid=grid, rc=rc)
At this point we will extract each of the Fields in the FieldBundle in turn and change the value of one Attribute in the original Attribute package, add a nested Attribute package, and delete one other of the Attributes in the original Attribute package. These three changes represent, respectively, a value change and two structural changes to the Attribute hierarchy during run time, which must be reconciled across the VM before the second gridded Component can be allowed to further manipulate the Attribute hierarchy.
do k = 1, 10 call ESMF_FieldBundleGet(fieldbundle, fieldIndex=k, field=field, rc=rc) call ESMF_AttributeSet(field, name2, value2, convention=convESMF, & purpose=purpGen, rc=status) call ESMF_AttributeAdd(field, convention=convESMF, purpose=purp2, & attrList=attrList, nestConvention=convESMF, nestPurpose=purpGen, & rc=rc) call ESMF_AttributeSet(field, name='Coordinates', value='Latlon', & convention=convESMF, purpose=purp2, rc=rc) call ESMF_AttributeSet(field, name='Mask', value='Yes', & convention=convESMF, purpose=purp2, rc=rc) call ESMF_AttributeRemove(field, name=name3, convention=convESMF, & purpose=purpGen, rc=status) enddo
At this point, the driver of the model run will transfer control to the run phase of the coupler Component.
In the run phase of the coupler Component we must now ensure that the entire VM again has a consistent view of the Attribute hierarchy. This is different from the communication done in the initialize phase of the model run because the only structural change that has occurred is in the Attribute hierarchy. Therefore an ESMF_AttributeUpdate() call can be used at this point to reconcile these changes. It should be noted that the ESMF_AttributeUpdate() call will reconcile value changes to the Attribute hierarchy as well as structural changes.
The first thing to do is to retrieve the Component, VM, and States. Then ESMF_AttributeUpdate() will be called on the import State to accomplish a VM wide communication. Afterwards, the Attribute hierarchy can be transfered, in a local sense, from the import State to the export State using an ESMF_AttributeCopy() call.
type(ESMF_VM) :: vm integer :: myPet integer, dimension(2) :: rootList rc = ESMF_SUCCESS call ESMF_CplCompGet(comp, vm=vm, rc=rc) call ESMF_VMGet(vm, localPet=myPet, rc=rc) call ESMF_StateGet(importState, rc=rc) call ESMF_StateGet(exportState, rc=rc) rootList = (/0,1/) call ESMF_AttributeUpdate(importState, vm, rootList=rootList, rc=rc) call ESMF_AttributeCopy(importState, exportState, & ESMF_COPY_ALIAS, ESMF_ATTTREE_ON, rc=rc)
At this point the entire VM has a consistent view of the Attribute hierarchy that was recently modified during run time in the first gridded component and the driver of the model run will transfer control to the run phase of the second gridded Component.
In the run phase of the second gridded Component is normally where a user model would again manipulate the data it was given. In this simple example we are only dealing with the metadata, which has already been ensured for consistency across the VM, including the exclusive piece of which is being used in this Component. Therefore we are free to use the metadata as we wish, considering only that any changes we make to it during run time will have to first be reconciled before other parts of the VM can use them. However, this is not our concern at this point because we will now explore the capabilities of ESMF_AttributeWrite().
First we will get the Component and VM. Then we will write out the Attribute hierarchy to an .xml file, after which we will write out the Attribute hierarchy to a more reader friendly tab-delimited format. Both of these write calls will output their respective data into files in the execution directory, in either a .xml or .stdout file.
type(ESMF_VM) :: vm integer :: petCount, status, myPet character(ESMF_MAXSTR) :: convESMF,purpGen rc = ESMF_SUCCESS call ESMF_GridCompGet(comp, vm=vm, rc=status) if (status .ne. ESMF_SUCCESS) return call ESMF_VMGet(vm, petCount=petCount, localPet=myPet, rc=status) if (status .ne. ESMF_SUCCESS) return convESMF = 'ESMF' purpGen = 'General' if (myPet .eq. 2) then call ESMF_AttributeWrite(importState,convESMF,purpGen, & attwriteflag=ESMF_ATTWRITE_XML, rc=rc) call ESMF_AttributeWrite(importState,convESMF,purpGen,rc=rc) if (rc .ne. ESMF_SUCCESS) return endif
At this point the driver of the model run would normally transfer control to the finalize phase of the first gridded Component. However, there is not much of interest as far as metadata is concerned in this portion of the model run. So with that we will conclude this example.
This example demonstrates the ability to access object information through the Attribute class. This capability is enabled only in the Grid class at this point. Internal Grid information is retrieved through the ESMF_AttributeGet() interface by specifying the name as a character string holding the keyword of the desired piece of Grid information. Information that requires input arguments is retrieved by specifying the input argument in a character array.
Some examples of this capability are given in this section. The first shows how to get the name of a Grid, and the second shows how to get a more complex parameter which requires inputs. First, we must initialize ESMF, declare some variables, and create a Grid:
! Use ESMF framework module use ESMF use ESMF_TestMod implicit none ! Local variables integer :: rc, finalrc, petCount, localPet, result type(ESMF_VM) :: vm type(ESMF_Grid) :: grid type(ESMF_DistGrid) :: distgrid character(ESMF_MAXSTR) :: name character(ESMF_MAXSTR),dimension(3) :: inputList integer(ESMF_KIND_I4) :: exclusiveLBound(2), exclusiveUBound(2) integer(ESMF_KIND_I4) :: exclusiveCount(2) character(ESMF_MAXSTR) :: testname character(ESMF_MAXSTR) :: failMsg
! initialize ESMF finalrc = ESMF_SUCCESS call ESMF_Initialize(vm=vm, & defaultlogfilename="AttributeInternalInfoEx.Log", & logkindflag=ESMF_LOGKIND_MULTI, rc=rc) distgrid=ESMF_DistGridCreate(minIndex=(/1,1/),maxIndex=(/10,10/), rc=rc)
grid=ESMF_GridCreate(distgrid=distgrid, & coordTypeKind=ESMF_TYPEKIND_I4, & name="AttributeTestGrid", rc=rc)
This first call shows how to retrieve the name of a Grid. The return value is a character string in this case, which must be provided as the argument to 'value'. The 'name' of the Attribute is specified as a character string whose value is the keyword of the piece of Grid information to retrieve preceded by a special tag. This tag, 'ESMF:', tells the ESMF_AttributeGet() routine that it should be looking for class information, rather than an Attribute that was previously created with the ESMF_AttributeSet() call.
call ESMF_AttributeGet(grid, name="ESMF:name", value=name, rc=rc)
This second call demonstrates how to retrieve the exclusiveCount from a Grid. As before, the 'name' of the Attribute is specified as the keyword of the information to retrieve, preceded by the 'ESMF:' tag. The value is an integer array, which must be allocated to a sufficient size to hold all of the requested information. The exclusiveCount of a Grid requires three pieces of input information: localDe, itemflag, and staggerloc. These are specified in an array of character strings. The name of the input parameter is separated from the value by a ':'.
inputList(:) = '' inputList(1) = 'localDe:0' inputList(2) = 'itemflag:ESMF_GRIDITEM_MASK' inputList(3) = 'staggerloc:ESMF_STAGGERLOC_CENTER' call ESMF_AttributeGet(grid, name="ESMF:exclusiveCount", & valueList=exclusiveCount, inputList=inputList, rc=rc)
That all there is to it! Now we just have to Finalize ESMF:
call ESMF_Finalize(rc=rc)
This example illustrates the use of the Metafor CIM Attribute packages, supplied by ESMF, to create an Attribute hierarchy on an ESMF object tree. A gridded Component is used together with a State and a realistic Field to create a simple ESMF object tree. CIM Attributes packages are created on the Component and Field, and then the individual Attributes within the packages are populated with values. Finally, all the Attributes are written to a CIM-formatted XML file. For a more comprehensive example, see the ESMF_AttributeCIM system test.
! Use ESMF framework module use ESMF use ESMF_TestMod implicit none ! Local variables integer :: rc, finalrc, petCount, localPet, result type(ESMF_VM) :: vm type(ESMF_Field) :: ozone type(ESMF_State) :: exportState type(ESMF_GridComp) :: gridcomp character(ESMF_MAXSTR) :: convCIM, purpComp, purpProp character(ESMF_MAXSTR) :: purpField, purpPlatform character(ESMF_MAXSTR) :: convISO, purpRP, purpCitation character(ESMF_MAXSTR), dimension(2) :: compPropAtt character(ESMF_MAXSTR) :: testname character(ESMF_MAXSTR) :: failMsg
! initialize ESMF finalrc = ESMF_SUCCESS call ESMF_Initialize(vm=vm, defaultlogfilename="AttributeCIMEx.Log", & logkindflag=ESMF_LOGKIND_MULTI, rc=rc) if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) ! get the vm call ESMF_VMGet(vm, petCount=petCount, localPet=localPet, rc=rc) if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT)
Create the ESMF objects that will hold the CIM Attributes. These objects include a gridded Component, a State, and a Field. In this example we are constructing empty Fields without an underlying Grid.
! Create Component gridcomp = ESMF_GridCompCreate(name="gridded_component", & petList=(/0/), rc=rc)
! Create State exportState = ESMF_StateCreate(name="exportState", & stateintent=ESMF_STATEINTENT_EXPORT, rc=rc)
! Create Field ozone = ESMF_FieldEmptyCreate(name='ozone', rc=rc)
Now add CIM Attribute packages to the Component and Field. Also, add a CIM Component Properties package, to contain two custom attributes.
convCIM = 'CIM' purpComp = 'Model Component Simulation Description' purpProp = 'General Component Properties Description' purpField = 'Inputs Description' purpPlatform = 'Platform Description' convISO = 'ISO 19115' purpRP = 'Responsible Party Description' purpCitation = 'Citation Description' ! Add CIM Attribute package to the gridded Component call ESMF_AttributeAdd(gridcomp, convention=convCIM, & purpose=purpComp, rc=rc)
! Specify the gridded Component to have a Component Properties ! package with two custom attributes, with user-specified names compPropAtt(1) = 'SimulationType' compPropAtt(2) = 'SimulationURL' call ESMF_AttributeAdd(gridcomp, convention=convCIM, purpose=purpProp, & attrList=compPropAtt, rc=rc)
! Add CIM Attribute package to the Field call ESMF_AttributeAdd(ozone, convention=convCIM, purpose=purpField, & rc=rc)
The standard Attribute package supplied by ESMF for a CIM Component contains several Attributes, grouped into sub-packages. These Attributes conform to the CIM convention as defined by Metafor and their values are set individually.
! ! Top-level model component attributes, set on gridded component ! call ESMF_AttributeSet(gridcomp, 'ShortName', 'EarthSys_Atmos', & convention=convCIM, purpose=purpComp, rc=rc)
call ESMF_AttributeSet(gridcomp, 'LongName', & 'Earth System High Resolution Global Atmosphere Model', & convention=convCIM, purpose=purpComp, rc=rc)
call ESMF_AttributeSet(gridcomp, 'Description', & 'EarthSys brings together expertise from the global ' // & 'community in a concerted effort to develop coupled ' // & 'climate models with increased horizontal resolutions. ' // & 'Increasing the horizontal resolution of coupled climate ' // & 'models will allow us to capture climate processes and ' // & 'weather systems in much greater detail.', & convention=convCIM, purpose=purpComp, rc=rc)
call ESMF_AttributeSet(gridcomp, 'Version', '2.0', & convention=convCIM, purpose=purpComp, rc=rc)
call ESMF_AttributeSet(gridcomp, 'ReleaseDate', '2009-01-01T00:00:00Z', & convention=convCIM, purpose=purpComp, rc=rc)
call ESMF_AttributeSet(gridcomp, 'ModelType', 'aerosol', & convention=convCIM, purpose=purpComp, rc=rc)
call ESMF_AttributeSet(gridcomp, 'URL', & 'www.earthsys.org', convention=convCIM, purpose=purpComp, rc=rc)
call ESMF_AttributeSet(gridcomp, 'MetadataVersion', '1.1', & convention=convCIM, purpose=purpComp, rc=rc)
! Simulation run attributes call ESMF_AttributeSet(gridcomp, 'SimulationShortName', & 'SMS.f09_g16.X.hector', & convention=convCIM, purpose=purpComp, rc=rc)
call ESMF_AttributeSet(gridcomp, 'SimulationLongName', & 'EarthSys - Earth System Modeling Framework Earth System Model 1.0', & convention=convCIM, purpose=purpComp, rc=rc)
call ESMF_AttributeSet(gridcomp, 'SimulationRationale', & 'EarthSys-ESMF simulation run in repsect to CMIP5 core experiment 1.1 ()', & convention=convCIM, purpose=purpComp, rc=rc)
call ESMF_AttributeSet(gridcomp, 'SimulationStartDate', & '1960-01-01T00:00:00Z', & convention=convCIM, purpose=purpComp, rc=rc)
call ESMF_AttributeSet(gridcomp, 'SimulationDuration', 'P10Y', & convention=convCIM, purpose=purpComp, rc=rc)
call ESMF_AttributeSet(gridcomp, & 'SimulationNumberOfProcessingElements', '16', & convention=convCIM, purpose=purpComp, rc=rc)
! Document genealogy call ESMF_AttributeSet(gridcomp, 'PreviousVersion', & 'EarthSys1 Atmosphere', & convention=convCIM, purpose=purpComp, rc=rc)
call ESMF_AttributeSet(gridcomp, 'PreviousVersionDescription', & 'Horizontal resolution increased to 1.20 x 0.80 degrees; ' // & 'Timestep reduced from 30 minutes to 15 minutes.', & convention=convCIM, purpose=purpComp, rc=rc)
! Platform description attributes call ESMF_AttributeSet(gridcomp, 'CompilerName', 'Pathscale', & convention=convCIM, purpose=purpPlatform, rc=rc)
call ESMF_AttributeSet(gridcomp, 'CompilerVersion', '3.0', & convention=convCIM, purpose=purpPlatform, rc=rc)
call ESMF_AttributeSet(gridcomp, 'MachineName', 'HECToR', & convention=convCIM, purpose=purpPlatform, rc=rc)
call ESMF_AttributeSet(gridcomp, 'MachineDescription', & 'HECToR (Phase 2a) is currently an integrated system known ' // & 'as Rainier, which includes a scalar MPP XT4 system, a vector ' // & 'system known as BlackWidow, and storage systems.', & convention=convCIM, purpose=purpPlatform, rc=rc)
call ESMF_AttributeSet(gridcomp, 'MachineSystem', 'Parallel', & convention=convCIM, purpose=purpPlatform, rc=rc) call ESMF_AttributeSet(gridcomp, 'MachineOperatingSystem', 'Unicos', & convention=convCIM, purpose=purpPlatform, rc=rc) call ESMF_AttributeSet(gridcomp, 'MachineVendor', 'Cray Inc', & convention=convCIM, purpose=purpPlatform, rc=rc) call ESMF_AttributeSet(gridcomp, 'MachineInterconnectType', & 'Cray Interconnect', & convention=convCIM, purpose=purpPlatform, rc=rc)
call ESMF_AttributeSet(gridcomp, 'MachineMaximumProcessors', '22656', & convention=convCIM, purpose=purpPlatform, rc=rc)
call ESMF_AttributeSet(gridcomp, 'MachineCoresPerProcessor', '4', & convention=convCIM, purpose=purpPlatform, rc=rc)
call ESMF_AttributeSet(gridcomp, 'MachineProcessorType', 'AMD X86_64', & convention=convCIM, purpose=purpPlatform, rc=rc)
! Component Properties: custom attributes call ESMF_AttributeSet(gridcomp, 'SimulationType', 'branch', & convention=convCIM, purpose=purpProp, rc=rc)
call ESMF_AttributeSet(gridcomp, 'SimulationURL', & 'http://earthsys.org/simulations', & convention=convCIM, purpose=purpProp, rc=rc)
Set the attribute values of the Responsible Party sub-package, created above for the gridded Component in the ESMF_AttributeAdd(gridcomp, ...) call.
! Responsible party attributes (for Principal Investigator) call ESMF_AttributeSet(gridcomp, 'Name', 'John Doe', & convention=convISO, purpose=purpRP, rc=rc) call ESMF_AttributeSet(gridcomp, 'Abbreviation', 'JD', & convention=convISO, purpose=purpRP, rc=rc) call ESMF_AttributeSet(gridcomp, 'PhysicalAddress', & 'Department of Meteorology, University of ABC', & convention=convISO, purpose=purpRP, rc=rc) call ESMF_AttributeSet(gridcomp, 'EmailAddress', & 'john.doe@earthsys.org', & convention=convISO, purpose=purpRP, rc=rc) call ESMF_AttributeSet(gridcomp, 'ResponsiblePartyRole', 'PI', & convention=convISO, purpose=purpRP, rc=rc)
call ESMF_AttributeSet(gridcomp, 'URL', 'www.earthsys.org', & convention=convISO, purpose=purpRP, rc=rc)
Set the attribute values of the Citation sub-package, created above for the gridded Component in the ESMF_AttributeAdd(gridcomp, ...) call.
! Citation attributes call ESMF_AttributeSet(gridcomp, 'ShortTitle', 'Doe_2009', & convention=convISO, purpose=purpCitation, rc=rc) call ESMF_AttributeSet(gridcomp, 'LongTitle', & 'Doe, J.A.; Norton, A.B.; ' // & 'Clark, G.H.; Davies, I.J.. 2009 EarthSys: ' // & 'The Earth System High Resolution Global Atmosphere Model - Model ' // & 'description and basic evaluation. Journal of Climate, 15 (2). ' // & '1261-1296.', & convention=convISO, purpose=purpCitation, rc=rc)
call ESMF_AttributeSet(gridcomp, 'Date', '2010-03-15', & convention=convISO, purpose=purpCitation, rc=rc)
call ESMF_AttributeSet(gridcomp, 'PresentationForm', 'Online Refereed', & convention=convISO, purpose=purpCitation, rc=rc)
call ESMF_AttributeSet(gridcomp, 'DOI', 'doi:17.1035/2009JCLI4508.1', & convention=convISO, purpose=purpCitation, rc=rc)
call ESMF_AttributeSet(gridcomp, 'URL', & 'http://www.earthsys.org/publications', & convention=convISO, purpose=purpCitation, rc=rc)
The standard Attribute package currently supplied by ESMF for CIM Fields contains a standard CF-Extended package nested within it.
! ozone CF-Extended Attributes call ESMF_AttributeSet(ozone, 'ShortName', 'Global_O3_mon', & convention=convCIM, purpose=purpField, rc=rc) call ESMF_AttributeSet(ozone, 'StandardName', 'ozone', & convention=convCIM, purpose=purpField, rc=rc) call ESMF_AttributeSet(ozone, 'LongName', 'ozone', & convention=convCIM, purpose=purpField, rc=rc) call ESMF_AttributeSet(ozone, 'Units', 'unknown', & convention=convCIM, purpose=purpField, rc=rc)
! ozone CIM Attributes call ESMF_AttributeSet(ozone, 'CouplingPurpose', 'Boundary', & convention=convCIM, purpose=purpField, rc=rc)
call ESMF_AttributeSet(ozone, 'CouplingSource', 'EarthSys_Atmos', & convention=convCIM, purpose=purpField, rc=rc)
call ESMF_AttributeSet(ozone, 'CouplingTarget', & 'EarthSys_AtmosDynCore', convention=convCIM, & purpose=purpField, rc=rc)
call ESMF_AttributeSet(ozone, 'Description', & 'Global Ozone concentration ' // & 'monitoring in the atmosphere.', & convention=convCIM, purpose=purpField, rc=rc)
call ESMF_AttributeSet(ozone, 'SpatialRegriddingMethod', & 'Conservative-First-Order', & convention=convCIM, purpose=purpField, rc=rc)
call ESMF_AttributeSet(ozone, 'SpatialRegriddingDimension', '3D', & convention=convCIM, purpose=purpField, rc=rc)
call ESMF_AttributeSet(ozone, 'Frequency', '15 Minutes', & convention=convCIM, purpose=purpField, rc=rc)
call ESMF_AttributeSet(ozone, 'TimeTransformationType', & 'TimeInterpolation', & convention=convCIM, purpose=purpField, rc=rc)
Adding the Field to the State will automatically link the Attribute hierarchies from the State to the Field
! Add the Field directly to the State call ESMF_StateAdd(exportState, fieldList=(/ozone/), rc=rc)
The Attribute link between a Component and a State must be set manually.
! Link the State to the gridded Component call ESMF_AttributeLink(gridcomp, exportState, rc=rc)
Write the entire CIM Attribute hierarchy, beginning at the gridded Component (the top), to an XML file formatted to conform to CIM specifications. The CIM output tree structure differs from the internal Attribute hierarchy in that it has all the attributes of the fields within its top-level <modelComponent> record. The filename used, gridded_component.xml, is derived from the name of the gridded Component, given as an input argument in the ESMF_GridCompCreate() call above. The file is written to the examples execution directory.
call ESMF_AttributeWrite(gridcomp, convCIM, purpComp, & attwriteflag=ESMF_ATTWRITE_XML,rc=rc)
call ESMF_StateDestroy(exportState, rc=rc)
call ESMF_GridCompDestroy(gridcomp, rc=rc)
call ESMF_Finalize(rc=rc) 10 continue if (rc/=ESMF_SUCCESS) finalrc = ESMF_FAILURE call ESMF_Finalize(rc=rc) if (rc/=ESMF_SUCCESS) finalrc = ESMF_FAILURE if (finalrc==ESMF_SUCCESS) then print *, "PASS: ESMF_AttributeCIMEx.F90" else print *, "FAIL: ESMF_AttributeCIMEx.F90" endif end program
! ESMF Framework module use ESMF use ESMF_TestMod implicit none ! local variables type(ESMF_GridComp) :: gridcomp character(ESMF_MAXSTR) :: attrvalue type(ESMF_VM) :: vm integer :: rc, petCount, localPet
! initialize ESMF call ESMF_Initialize(vm=vm, defaultlogfilename="AttReadGridCompEx.Log", & logkindflag=ESMF_LOGKIND_MULTI, rc=rc)
! get the vm call ESMF_VMGet(vm, petCount=petCount, localPet=localPet, rc=rc)
if (petCount<4) then gridcomp = ESMF_GridCompCreate(name="gridcomp", & petList=(/0/), rc=rc) else gridcomp = ESMF_GridCompCreate(name="gridcomp", & petList=(/0,1,2,3/), rc=rc) endif
! Read an XML file to populate the ESG Attribute package of a GridComp. ! The file is validated against an internal, ESMF-supplied XSD file ! defining the standard ESG Component Attribute package (see file ! pathnames above). call ESMF_AttributeRead(comp=gridcomp, fileName="esmf_gridcomp.xml", & rc=rc)
! Get ESG "ComponentShortName" Attribute from a GridComp call ESMF_AttributeGet(gridcomp, name='ComponentShortName', & value=attrValue, & convention='ESG', purpose='General', rc=rc)
! Get ESG "ComponentLongName" Attribute from a GridComp call ESMF_AttributeGet(gridcomp, name='ComponentLongName', & value=attrValue, & convention='ESG', purpose='General', rc=rc)
! Get ESG "Agency" Attribute from a GridComp call ESMF_AttributeGet(gridcomp, name='Agency', value=attrValue, & convention='ESG', purpose='General', rc=rc)
! Get ESG "Institution" Attribute from a GridComp call ESMF_AttributeGet(gridcomp, name='Institution', value=attrValue, & convention='ESG', purpose='General', rc=rc)
! Get ESG "Version" Attribute from a GridComp call ESMF_AttributeGet(gridcomp, name='Version', value=attrValue, & convention='ESG', purpose='General', rc=rc)
! Get ESG "Author" Attribute from a GridComp call ESMF_AttributeGet(gridcomp, name='Author', value=attrValue, & convention='ESG', purpose='General', rc=rc)
! Get ESG "Discipline" Attribute from a GridComp call ESMF_AttributeGet(gridcomp, name='Discipline', value=attrValue, & convention='ESG', purpose='General', rc=rc)
! Get ESG "PhysicalDomain" Attribute from a GridComp call ESMF_AttributeGet(gridcomp, name='PhysicalDomain', & value=attrValue, convention='ESG', & purpose='General', rc=rc)
! Get ESG "CodingLanguage" Attribute from a GridComp Test call ESMF_AttributeGet(gridcomp, name='CodingLanguage', & value=attrValue, convention='ESG', & purpose='General', rc=rc)
! Get ESG "ModelComponentFramework" Attribute from a GridComp call ESMF_AttributeGet(gridcomp, name='ModelComponentFramework', & value=attrValue, & convention='ESG', purpose='General', rc=rc)
call ESMF_GridCompDestroy(gridcomp, rc=rc)
! finalize ESMF framework call ESMF_Finalize(rc=rc)
! ESMF Framework module use ESMF use ESMF_TestMod implicit none ! local variables type(ESMF_Field) :: field character(ESMF_MAXSTR) :: attrvalue type(ESMF_VM) :: vm integer :: rc
! initialize ESMF call ESMF_Initialize(vm=vm, defaultlogfilename="AttReadFieldEx.Log", & logkindflag=ESMF_LOGKIND_MULTI, rc=rc)
! Create a field field = ESMF_FieldEmptyCreate(name="field", rc=rc)
! Read an XML file to populate the CF Attribute package of a Field. ! The file is validated against an internal, ESMF-supplied XSD file ! defining the standard CF Attribute package (see file pathnames above). call ESMF_AttributeRead(field=field, fileName="esmf_field.xml", rc=rc)
! Get CF "ShortName" Attribute from a Field call ESMF_AttributeGet(field, name='ShortName', value=attrValue, & convention='CF', purpose='General', rc=rc)
! Get CF "StandardName" Attribute from a Field call ESMF_AttributeGet(field, name='StandardName', & value=attrValue, & convention='CF', purpose='Extended', rc=rc)
! Get CF "LongName" Attribute from a Field call ESMF_AttributeGet(field, name='LongName', value=attrValue, & convention='CF', purpose='General', rc=rc)
! Get CF "Units" Attribute from a Field call ESMF_AttributeGet(field, name='Units', value=attrValue, & convention='CF', purpose='General', rc=rc)
call ESMF_FieldDestroy(field, rc=rc)
! finalize ESMF framework call ESMF_Finalize(rc=rc)
! ESMF Framework module use ESMF use ESMF_TestMod implicit none ! local variables type(ESMF_Grid) :: grid character(ESMF_MAXSTR) :: attrvalue type(ESMF_VM) :: vm integer :: rc
! initialize ESMF call ESMF_Initialize(vm=vm, & defaultlogfilename="AttReadGridEx.Log", & logkindflag=ESMF_LOGKIND_MULTI, rc=rc)
! Create a grid grid = ESMF_GridEmptyCreate(rc=rc)
! Read an XML file to populate the GridSpec Attribute package of a Grid. ! The file is validated against an internal, ESMF-supplied XSD file ! defining the standard GridSpec Attribute package (see file pathnames ! above). call ESMF_AttributeRead(grid=grid, fileName="esmf_grid.xml", rc=rc)
! Get GridSpec "GridType" Attribute from a Grid call ESMF_AttributeGet(grid, name='GridType', value=attrValue, & convention='GridSpec', purpose='General', rc=rc)
! Get GridSpec "CongruentTiles" Attribute from a Grid call ESMF_AttributeGet(grid, name='CongruentTiles', value=attrValue, & convention='GridSpec', purpose='General', rc=rc)
! Get GridSpec "NumberOfGridTiles" Attribute from a Grid call ESMF_AttributeGet(grid, name='NumberOfGridTiles', & value=attrValue, convention='GridSpec', & purpose='General', rc=rc)
! Get GridSpec "DimensionOrder" Attribute from a Grid call ESMF_AttributeGet(grid, name='DimensionOrder', value=attrValue, & convention='GridSpec', purpose='General', rc=rc)
! Get GridSpec "DiscretizationType" Attribute from a Grid call ESMF_AttributeGet(grid, name='DiscretizationType', & value=attrValue, & convention='GridSpec', purpose='General', rc=rc)
! Get GridSpec "GeometryType" Attribute from a Grid call ESMF_AttributeGet(grid, name='GeometryType', value=attrValue, & convention='GridSpec', purpose='General', rc=rc)
! Get GridSpec "IsConformal" Attribute from a Grid call ESMF_AttributeGet(grid, name='IsConformal', value=attrValue, & convention='GridSpec', purpose='General', rc=rc)
! Get GridSpec "IsRegular" Attribute from a Grid call ESMF_AttributeGet(grid, name='IsRegular', value=attrValue, & convention='GridSpec', purpose='General', rc=rc)
! Get GridSpec "IsUniform" Attribute from a Grid call ESMF_AttributeGet(grid, name='IsUniform', value=attrValue, & convention='GridSpec', purpose='General', rc=rc)
! Get GridSpec "NorthPoleLocation" Attribute from a Grid call ESMF_AttributeGet(grid, name='NorthPoleLocation', & value=attrValue, & convention='GridSpec', purpose='General', rc=rc)
! Get GridSpec "NumberOfCells" Attribute from a Grid call ESMF_AttributeGet(grid, name='NumberOfCells', value=attrValue, & convention='GridSpec', purpose='General', rc=rc)
! Get GridSpec "NX" Attribute from a Grid call ESMF_AttributeGet(grid, name='NX', value=attrValue, & convention='GridSpec', purpose='General', rc=rc)
! Get GridSpec "NY" Attribute from a Grid call ESMF_AttributeGet(grid, name='NY', value=attrValue, & convention='GridSpec', purpose='General', rc=rc)
! Get GridSpec "HorizontalResolution" Attribute from a Grid call ESMF_AttributeGet(grid, name='HorizontalResolution', & value=attrValue, convention='GridSpec', & purpose='General', rc=rc)
call ESMF_GridDestroy(grid, rc=rc)
! finalize ESMF framework call ESMF_Finalize(rc=rc)
! ESMF Framework module use ESMF use ESMF_TestMod implicit none ! local variables type(ESMF_CplComp) :: cplcomp character(ESMF_MAXSTR) :: attrvalue type(ESMF_VM) :: vm integer :: rc, petCount, localPet
! initialize ESMF call ESMF_Initialize(vm=vm, & defaultlogfilename="AttReadCustCplCompEx.Log", & logkindflag=ESMF_LOGKIND_MULTI, rc=rc)
! get the vm call ESMF_VMGet(vm, petCount=petCount, localPet=localPet, rc=rc)
if (petCount<4) then cplcomp = ESMF_CplCompCreate(name="cplcomp", & petList=(/0/), rc=rc) else cplcomp = ESMF_CplCompCreate(name="cplcomp", & petList=(/0,1,2,3/), rc=rc) endif
! Read an XML file to decorate a Coupler Component with custom, ! user-defined attributes, and validate them against a corresponding ! XSD schema file (see file pathnames above). call ESMF_AttributeRead(comp=cplcomp, fileName="custom_cplcomp.xml", & schemaFileName="custom_cplcomp.xsd", rc=rc)
! Get custom "MyAttribute1" from CplComp call ESMF_AttributeGet(cplcomp, name='MyAttribute1', value=attrValue, & rc=rc)
! Get custom "MyAttribute2" from CplComp call ESMF_AttributeGet(cplcomp, name='MyAttribute2', value=attrValue, & rc=rc)
! Get custom "MyAttribute3" from CplComp call ESMF_AttributeGet(cplcomp, name='MyAttribute3', value=attrValue, & rc=rc)
! Get custom "MyAttribute4" from CplComp call ESMF_AttributeGet(cplcomp, name='MyAttribute4', value=attrValue, & rc=rc)
! Get custom "MyAttribute5" from CplComp call ESMF_AttributeGet(cplcomp, name='MyAttribute5', value=attrValue, & rc=rc)
call ESMF_CplCompDestroy(cplcomp, rc=rc)
! finalize ESMF framework call ESMF_Finalize(rc=rc)
This section covers Attribute memory deallocation, the use of ESMF_AttributeGet(), Attribute package nesting capabilities, issues with Attributes in a distributed environment, and reading/writing of Attributes via XML files. Issues and procedures dealing with Attribute memory deallocation, using ESMF_AttributeGet() to retrieve Attribute lists, and nested Attribute package capabilities are discussed to help avoid misuse. The limitations with Attributes in a distributed environment are also discussed, with an outline of the future work to be done in this area.
The Attribute class presents a somewhat different paradigm with respect to memory deallocation than other ESMF objects. The ESMF_AttributeRemove() call can be issued to remove any Attribute from an ESMF object or an Attribute package on an ESMF object. This call is also enabled to remove entire Attribute packages with one call, which would remove any nested Attribute packages as well. The user is not required to remove all Attributes that are used in a model run. The entire Attribute hierarchy will be removed automatically by ESMF, provided the ESMF objects which contain them are properly destroyed.
The decision to remove either an Attribute or an Attribute package is made by calling ESMF_AttributeRemove() with the correct optional arguments. If an Attribute which is not associated with any Attribute package should be removed, then the call must be issued without a convention or purpose argument. If an Attribute in an Attribute package is to be removed, then the call should be issued with all three of name, convention, and purpose. Finally, if an entire Attribute package is to be removed the call should be issued with a convention and purpose, but no Attribute name.
The behavior of the ESMF_AttributeGet() routine, when retrieving an Attribute containing a value list, follows a slightly different convention than other similar ESMF routines. This routine requires the input of a Fortran array as a place to store the retrieved values of the Attribute list. If the array that is given is longer that the list of Attribute values, the first part of the array will be filled, leaving the extra space untouched. If, however, the array passed in is shorter than the number of Attribute values, the routine will exit with a return code which is not equal to ESMF_SUCCESS. It is suggested that if it is required by the user to use a Fortran array that is longer than the number of Attribute values returned, only the indices of the array which the user desires to be filled with retrieved Attribute values should be passed into the routine.
Similar behavior is exhibited with the defaultvalueList argument in the ESMF_AttributeGet() routine. The difference here is that if the valueList is shorter than the defaultvalueList only the appropriate values will be filed in, and the routine will exit without error. Likewise, if the valueList is longer than the defaultvalueList then the entire valueList will be populated with the beginning section of the defaultvalueList that is given.
There is a recommended practice to organizing metadata conventions when using nested Attribute packages. The most general Attribute packages should always be added first, followed by the more specific ones. For instance, when adding Attribute packages to a Field, it is recommended that the CF convention be added first, followed by the ESG convention, followed by any additional customized Attribute packages.
At this time there are several ESMF supplied Attribute packages, with a convention of ESMF and a purpose of General. These Attribute packages are generated by calling ESMF_AttributeAdd() with the appropriate convention and purpose. The ESMF standard Attribute packages can be customized by nesting a custom Attribute package around them; they can also be modified in other ways but this is not suggested practice at this time.
Another consideration when using nested Attribute packages is to remember that when a nested Attribute package is removed every nested Attribute package below the point of removal will also be removed (like pruning a tree branch). Thus, by removing the ESG Attribute package on a Field, the CF Attribute package contained within it will also be removed.
This section discusses the methods of building a consistent view of the metadata across the VM of a model run. To better explain the ESMF capabilities for ensuring the integrity of Attributes in a distributed environment, a small working vocabulary of ESMF Attributes will be presented. Three types of changes to an Attribute hierarchy need to be specified, these are: 1. link changes are structural links created when two separate Attribute hierarchies are linked, 2. structural changes are changes which occur when Attributes or Attribute packages are added or removed within a single level of an Attribute hierarchy, and 3. value changes occur when the value portion of any single Attribute is modified. These definitions will help to describe how ESMF_StateReconcile() and ESMF_AttributeUpdate() can be effectively used to ensure a consistent view of the metadata throughout a model run.
The ESMF_StateReconcile() call is used to create a consistent view of ESMF objects over the entire VM in the initialization phase of a model run. All Attributes that are attached to an ESMF object contained in the State, i.e. an object that is being reconciled, can also be reconciled. This is done by setting a flag in the ESMF_StateReconcile() call, see the State documentation for details. This means that, at the conclusion of ESMF_StateReconcile() there is a one-to-one correspondence between Attribute hierarchies and the ESMF objects they represent. This is the only place where link changes in an Attribute hierarchy can be resolved.
The ESMF_AttributeUpdate() call can be used any time during the run phase of a model to insure that either structural or value changes made to an Attribute hierarchy on a subset of the VM are consistently represented across the remainder of the VM. At this time, link changes cannot be resolved by ESMF_AttributeUpdate() as this would represent a departure from the one-to-one correspondence between the Attribute hierarchy and the ESMF objects it represents. This means that ESMF_AttributeUpdate() will only work if it is called after ESMF_StateReconcile() when link changes have been made.
ESMF_AttributeUpdate() is similar to ESMF_StateReconcile() in that it must be called from a location that has a view of the entire VM across which to update the Attribute hierarchy, such as a coupler Component. The main difference is that ESMF_AttributeUpdate() operates only on the underlying Attribute hierarchy of the given ESMF object. The Attribute hierarchy may be updated as many times as necessary, this call is much more efficient than ESMF_StateReconcile() for this reason.
The specification of a list of PETs that are to be used as the basis for the update is a key feature of this interface. This allows a many-to-many communication, as well as the direct specification of which PETs are to be updated and which are to be used as the "real" values. The information is basically transported from the Attributes on the PETs specified in the rootList to their counterparts on the PETs which are not specified in the rootList. This means that care must be taken to ensure that the data on the PETs in the rootList is consistent.
One caveat with this routine is that upon completion the destination PETs will have all of the missing Attributes from the source PETs, but this is not true the other way around. This basically boils down to the fact that the end product of calling ESMF_AttributeUpdate() is not the union of the Attributes on both source and destination PETs. This can be achieved, however, by calling ESMF_AttributeUpdate() twice, once from source to destination, and then again from destination to source.
The ESMF_AttributeWrite() interface is in limited form at the present time, as it can only be used reliably on the ESMF standard Attribute packages. Chances are that it will perform as expected for most Attribute packages, but for now it is only guaranteed for the ESMF standard Attribute packages. This routine is also not yet enabled to handle multi-valued Attributes. One thing to remember when using this interface is that if you are writing an Attribute package that contains nested Attribute packages then all Attribute nested below the top level Attribute package will be written.
The ability to copy an Attribute hierarchy is limited at this time. The ESMF_AttributeCopy() routine can be used to locally copy an Attribute hierarchy between two States or Components. It is important to note that this is a local copy, and no inter-PET communication is carried out. Another thing to note is that when this functionality is based on a reference copy any further changes made to some portions of the original Attribute hierarchy will also affect the new Attribute hierarchy.
There are two flags in the ESMF_AttributeCopy() routine which specify which type of copy is desired. At this point there are only two different varieties of Attribute hierarchy copies available. One of the requires the ESMF_Copy_Flag to be set to ESMF_COPY_VALUE and the ESMF_AttTreeFlag to be set to ESMF_ATTTREE_OFF. This does a copy of only the first level of an Attribute hierarchy, by value.
The second available copy can be applied by setting the ESMF_Copy_Flag to ESMF_COPY_ALIAS and the ESMF_AttTreeFlag to ESMF_ATTTREE_ON. This copy is more of a hybrid approach of reference and value copies. In this case the Attributes which belong to the object being copied are actually copied in full (by value), while the Attributes which are linked to the object being copied are referenced by a pointer (by reference). This means that after copying an Attribute hierarchy from ESMF object A to ESMF object B with this approach, the changes made to the lower portion of either A or B's Attribute hierarchy will be reflected on both object A and object B.
The Xerces C++ library, v3.1.0 or better, is used to read XML files. More specifically, the SAX2 API is currently used, although future releases may also use the DOM API. The Xerces C++ website is http://xerces.apache.org/xerces-c/. For more details, see the "ESMF Users Guide", "Building and Installing the ESMF, Third Party Libraries, Xerces". Also please see the section on Attribute I/O, 33.2. Writing Attribute XML files is performed with the standard C++ output file stream facility.
Each Attribute contains a name-value pair in which the value can be any of several numeric, character, and logical types. Each value type is implemented as a vector, and can hold one or several values. The available ESMF Attribute value types include:
The other members of the Attribute class can be seen in Figure 29 below, which shows a UML representation of the ESMF Attribute class.
In addition to a name, all Attributes within an Attribute package are identified by a convention, purpose, and the ESMF object type with which they are associated. These are additional strings that are initialized as empty until specified.
Also, all Attributes contain three vectors of pointers to other Attributes, which are empty until specified otherwise. These vectors of Attribute pointers hold the Attributes, Attribute packages, and Attribute links. This feature is what allows the Attribute class to self assemble complex structures for representing and organizing the metadata of an ESMF object hierarchy.
For a more detailed view of how Attribute packages and hierarchies are formed, see Figures 30 and 31, respectively.
INTERFACE:
! Private name; call using ESMF_AttributeAdd() subroutine ESMF_AttAddPackStd(<object>, convention, purpose, rc)ARGUMENTS:
<object>, see below for supported values character (len = *), intent(in) :: convention character (len = *), intent(in) :: purpose integer, intent(out), optional :: rcDESCRIPTION:
Add an ESMF standard Attribute package. See Section 36.2 for a description of Attribute packages and their conventions, purposes, and object types.
Supported values for <object> are:
The arguments are:
INTERFACE:
! Private name; call using ESMF_AttributeAdd() subroutine ESMF_AttAddPackStdN(<object>, convention, purpose, & nestConvention, nestPurpose, nestAttPackInstanceCountList, & nestAttPackInstanceNameList, nestCount, & nestAttPackInstanceNameCount,rc)ARGUMENTS:
<object>, see below for supported values character (len = *), intent(in) :: convention character (len = *), intent(in) :: purpose character (len = *), intent(in) :: nestConvention(:) character (len = *), intent(in) :: nestPurpose(:) integer, intent(in) :: nestAttPackInstanceCountList(:) character (len = *), intent(out) :: nestAttPackInstanceNameList(:) integer, intent(in), optional :: nestCount integer, intent(out), optional :: nestAttPackInstanceNameCount integer, intent(out), optional :: rcDESCRIPTION:
Add an ESMF standard Attribute package which contains a user-specified number of nested standard Attribute packages. ESMF generates and returns default instance names for the nested Attribute packages. These names can be used later to distinguish among multiple nested Attribute packages of the same type in calls to ESMF_AttributeGet(), ESMF_AttributeSet(), and ESMF_AttributeRemove(). See Section 36.2 for a description of Attribute packages and their conventions, purposes, and object types.
Supported values for <object> are:
The arguments are:
INTERFACE:
! Private name; call using ESMF_AttributeAdd() subroutine ESMF_AttAddPackCst(<object>, convention, purpose, & attrList, count, rc)ARGUMENTS:
<object>, see below for supported values character (len = *), intent(in) :: convention character (len = *), intent(in) :: purpose character (len=*), intent(in) :: attrList(:) integer, intent(in), optional :: count integer, intent(out), optional :: rcDESCRIPTION:
Add a custom Attribute package to <object>. See Section 36.2 for a description of Attribute packages and their conventions, purposes, and object types.
Supported values for <object> are:
The arguments are:
INTERFACE:
! Private name; call using ESMF_AttributeAdd() subroutine ESMF_AttAddPackCstN(<object>, convention, purpose, & attrList, count, nestConvention, nestPurpose, nestCount, rc)ARGUMENTS:
<object>, see below for supported values character (len = *), intent(in) :: convention character (len = *), intent(in) :: purpose character (len=*), intent(in), optional :: attrList(:) integer, intent(in), optional :: count character (len = *), intent(in) :: nestConvention(:) character (len = *), intent(in) :: nestPurpose(:) integer, intent(in), optional :: nestCount integer, intent(out), optional :: rcDESCRIPTION:
Add a custom Attribute package, with one or more nested Attribute packages, to <object>. Allows for building full multiple-child Attribute hierarchies (multi-child trees). See Section 36.2 for a description of Attribute packages and their conventions, purposes, and object types.
Supported values for <object> are:
The arguments are:
INTERFACE:
! Private name; call using ESMF_AttributeAdd() subroutine ESMF_AttAddPackCstN1(<object>, convention, purpose, & attrList, count, nestConvention, nestPurpose, rc)ARGUMENTS:
<object>, see below for supported values character (len=*), intent(in) :: convention character (len=*), intent(in) :: purpose character (len=*), intent(in), optional :: attrList(:) integer, intent(in), optional :: count character (len=*), intent(in) :: nestConvention character (len=*), intent(in) :: nestPurpose integer, intent(out), optional :: rcDESCRIPTION:
Add a custom Attribute package, with a single nested Attribute package, to <object>. Allows for building single-child Attribute hierarchies (single-child trees). See Section 36.2 for a description of Attribute packages and their conventions, purposes, and object types.
Supported values for <object> are:
The arguments are:
INTERFACE:
! Private name; call using ESMF_AttributeCopy() subroutine ESMF_AttributeCopy(<object1>, <object2>, copyflag, & atttreeflag, rc)ARGUMENTS:
<object1>, see below for supported values <object2>, see below for supported values type(ESMF_Copy_Flag), intent(in) :: copyflag type(ESMF_AttTreeFlag), intent(in) :: atttreeflag integer, intent(out), optional :: rcDESCRIPTION:
Copy an Attribute hierarchy from <object1> to <object2>. Supported values for <object1> are:
NOTE: Copies between different ESMF objects are not possible at this time.
The arguments are:
INTERFACE:
subroutine ESMF_AttributeGet(<object>, name, <value argument>, & <defaultvalue argument>, convention, purpose, & attPackInstanceName, isPresent, rc)ARGUMENTS:
<object>, see below for supported values character (len = *), intent(in) :: name <value argument>, see below for supported values <defaultvalue argument>, see below for supported values character (len = *), intent(in), optional :: convention character (len = *), intent(in), optional :: purpose character (len = *), intent(in), optional :: attPackInstanceName logical, intent(out), optional :: isPresent integer, intent(out), optional :: rcDESCRIPTION:
Return an Attribute value from the <object>, or from an Attribute package on the <object>, specified by convention and purpose, and optionally attPackInstanceName. Internal information can also be retrieved from Grid objects by prepending 'ESMF:' to the name of the piece of information that is requested. See Section 36.5 for more information on which pieces of Grid data can be retrieved through this interface. A defaultvalue argument may be given if a return code is not desired when the Attribute is not found. See Section 36.2 for a description of Attribute packages and their conventions, purposes, and object types.
Supported values for <object> are:
The arguments are:
INTERFACE:
subroutine ESMF_AttributeGet(<object>, name, <valueList argument>, & <defaultvalueList argument>, convention, purpose, & attPackInstanceName, itemCount, isPresent, rc)ARGUMENTS:
<object>, see below for supported values character (len = *), intent(in) :: name <valueList argument>, see below for supported values <defaultvalueList argument>, see below for supported values character (len = *), intent(in), optional :: convention character (len = *), intent(in), optional :: purpose character (len = *), intent(in), optional :: attPackInstanceName integer, intent(out), optional :: itemCount logical, intent(out), optional :: isPresent integer, intent(out), optional :: rcDESCRIPTION:
Return an Attribute valueList from the <object>, or from an Attribute package on the <object>, specified by convention and purpose, and optionally attPackInstanceName. Internal information can also be retrieved from Grid objects by prepending 'ESMF:' to the name of the piece of information that is requested. See Section 36.5 for more information on which pieces of Grid data can be retrieved through this interface. A defaultvalueList list argument may be given if a return code is not desired when the Attribute is not found. See Section 36.2 for a description of Attribute packages and their conventions, purposes, and object types.
Supported values for <object> are:
The arguments are:
INTERFACE:
! Private name; call using ESMF_AttributeGet() subroutine ESMF_AttributeGetCount(<object>, count, attcountflag, rc)ARGUMENTS:
<object>, see below for supported values integer, intent(out) :: count type(ESMF_AttGetCountFlag), intent(in), optional :: attcountflag integer, intent(out), optional :: rcDESCRIPTION:
Return the Attribute count for <object>. Supported values for <object> are:
The arguments are:
INTERFACE:
! Private name; call using ESMF_AttributeGet() subroutine ESMF_AttributeGetInfoByNam(<object>, name, & convention, purpose, & attPackInstanceName, typekind, & itemCount, isPresent, rc)ARGUMENTS:
<object>, see below for supported values character (len = *), intent(in) :: name -- The following arguments require argument keyword syntax (e.g. rc=rc). -- character (len=*), intent(in), optional :: convention character (len=*), intent(in), optional :: purpose character (len=*), intent(in), optional :: attPackInstanceName type(ESMF_TypeKind_Flag), intent(out), optional :: typekind integer, intent(out), optional :: itemCount logical, intent(out), optional :: isPresent integer, intent(out), optional :: rcDESCRIPTION:
Return information associated with the named Attribute, including typekind and itemCount. Supported values for <object> are:
The arguments are:
Return code; equals ESMF_SUCCESS if there are no errors
INTERFACE:
! Private name; call using ESMF_AttributeGet() subroutine ESMF_AttributeGetInfoByNum(<object>, attributeIndex, name, & typekind, itemcount, rc)ARGUMENTS:
<object>, see below for supported values integer, intent(in) :: attributeIndex character (len = *), intent(out) :: name type(ESMF_TypeKind_Flag), intent(out), optional :: typekind integer, intent(out), optional :: itemCount integer, intent(out), optional :: rcDESCRIPTION:
Returns information associated with the indexed Attribute, including name, typekind and itemCount. Keep in mind that these indexes start from 1, as expected in a Fortran API. Supported values for <object> are:
The arguments are:
INTERFACE:
! Private name; call using ESMF_AttributeGet() subroutine ESMF_AttributeGetAPinstNames(<object>, convention, purpose, & attPackInstanceNameList, attPackInstanceNameCount, rc)ARGUMENTS:
<object>, see below for supported values character (len = *), intent(in), optional :: convention character (len = *), intent(in), optional :: purpose character (len = *), intent(out) :: attPackInstanceNameList(:) integer, intent(out) :: attPackInstanceNameCount integer, intent(out), optional :: rcDESCRIPTION:
Get the Attribute package instance names of the specified convention and purpose. Also get the number of such names. See Section 36.2 for a description of Attribute packages and their conventions, purposes, and object types.
Supported values for <object> are:
The arguments are:
INTERFACE:
! Private name; call using ESMF_AttributeLink() subroutine ESMF_CompAttLink(<object1>, <object2>, rc)ARGUMENTS:
<object1>, see below for supported values <object2>, see below for supported values integer, intent(out), optional :: rcDESCRIPTION:
Attach a CplComp or GridComp Attribute hierarchy to the hierarchy of a CplComp, GridComp, or State. Supported values for the <object1> are:
The arguments are:
hierarchy of a an Array, ArrayBundle, Field, FieldBundle, or State
INTERFACE:
! Private name; call using ESMF_AttributeLink() subroutine ESMF_StateAttLink(state, <object>, rc)ARGUMENTS:
type(ESMF\_State), intent(inout) :: state <object>, see below for supported values integer, intent(out), optional :: rcDESCRIPTION:
Attach a State Attribute hierarchy to the hierarchy of a Fieldbundle, Field, or another State. Supported values for the <object> are:
The arguments are:
INTERFACE:
! Private name; call using ESMF_AttributeLink() subroutine ESMF_FieldBundleAttLink(fieldbundle, field, rc)ARGUMENTS:
type(ESMF\_FieldBundle), intent(inout) :: fieldbundle type(ESMF\_Field), intent(inout) :: field integer, intent(out), optional :: rcDESCRIPTION:
Attach a FieldBundle Attribute hierarchy to the hierarchy of a Field.
The arguments are:
INTERFACE:
! Private name; call using ESMF_AttributeLink() subroutine ESMF_FieldAttLink(field, grid, rc)ARGUMENTS:
type(ESMF\_Field), intent(inout) :: field type(ESMF\_Grid), intent(inout) :: grid integer, intent(out), optional :: rcDESCRIPTION:
Attach a Field Attribute hierarchy to the hierarchy of a Grid.
The arguments are:
INTERFACE:
! Private name; call using ESMF_AttributeLink() subroutine ESMF_ArrayBundleAttLink(arraybundle, array, rc)ARGUMENTS:
type(ESMF\_ArrayBundle), intent(inout) :: arraybundle type(ESMF\_Array), intent(inout) :: array integer, intent(out), optional :: rcDESCRIPTION:
Attach an ArrayBundle Attribute hierarchy to the hierarchy of an Array.
The arguments are:
INTERFACE:
! Private name; call using ESMF_AttributeLinkRemove() subroutine ESMF_CompAttLinkRemove(<object1>, <object2>, rc)ARGUMENTS:
<object1>, see below for supported values <object2>, see below for supported values integer, intent(out), optional :: rcDESCRIPTION:
Unattach a CplComp or GridComp Attribute hierarchy from the hierarchy of a CplComp, GridComp, or State. Supported values for the <object1> are:
The arguments are:
the hierarchy of an Array, ArrayBundle, Field, FieldBundle, or State
INTERFACE:
! Private name; call using ESMF_AttributeLinkRemove() subroutine ESMF_StateAttLinkRemove(state, <object>, rc)ARGUMENTS:
type(ESMF\_State), intent(inout) :: state <object>, see below for supported values integer, intent(out), optional :: rcDESCRIPTION:
Unattach a State Attribute hierarchy from the hierarchy of a Fieldbundle, Field, or another State. Supported values for the <object> are:
The arguments are:
INTERFACE:
! Private name; call using ESMF_AttributeLinkRemove() subroutine ESMF_FieldBundleAttLinkRemove(fieldbundle, field, rc)ARGUMENTS:
type(ESMF\_FieldBundle), intent(inout) :: fieldbundle type(ESMF\_Field), intent(inout) :: field integer, intent(out), optional :: rcDESCRIPTION:
Unattach a FieldBundle Attribute hierarchy from the hierarchy of a Field.
The arguments are:
INTERFACE:
! Private name; call using ESMF_AttributeLinkRemove() subroutine ESMF_FieldAttLinkRemove(field, grid, rc)ARGUMENTS:
type(ESMF\_Field), intent(inout) :: field type(ESMF\_Grid), intent(inout) :: grid integer, intent(out), optional :: rcDESCRIPTION:
Unattach a Field Attribute hierarchy from the hierarchy of a Grid.
The arguments are:
INTERFACE:
! Private name; call using ESMF_AttributeLinkRemove() subroutine ESMF_ArrayBundleAttLinkRemove(arraybundle, array, rc)ARGUMENTS:
type(ESMF\_ArrayBundle), intent(inout) :: arraybundle type(ESMF\_Array), intent(inout) :: array integer, intent(out), optional :: rcDESCRIPTION:
Unattach an ArrayBundle Attribute hierarchy from the hierarchy of an Array.
The arguments are:
INTERFACE:
subroutine ESMF_AttributeRead(<object>, fileName, schemaFileName, & convention, purpose, rc)ARGUMENTS:
<object>, see below for supported values character (len=*), intent(in), optional :: fileName character (len=*), intent(in), optional :: schemaFileName character (len = *), intent(in), optional :: convention character (len = *), intent(in), optional :: purpose integer, intent(out), optional :: rcDESCRIPTION:
Read Attributes for <object> from fileName, whose format is XML. schemaFileName format is XSD. If present, the schemaFileName is used to validate the contents of fileName. schemaFileName must be specified for a fileName containing custom, user-defined Attributes. schemaFileName need not be specified for convention and purposes specifying a standard, ESMF-supplied Attribute package. If present, the convention and purpose specify an Attribute package which is used to filter the reading to just those attributes belonging to the Attribute package. See Section 36.2 for a description of Attribute packages and their conventions, purposes, and object types.
Requires the third party Xerces C++ XML Parser library to be installed,
v3.1.0 or better. For more details, see the "ESMF Users Guide",
"Building and Installing the ESMF, Third Party Libraries, Xerces" and
the website
"http://xerces.apache.org/xerces-c". Also please see the
section on Attribute I/O, 33.2.
Supported values for <object> are:
The arguments are:
INTERFACE:
subroutine ESMF_AttributeRemove(<object>, name, convention, purpose, & attPackInstanceName, rc)ARGUMENTS:
<object>, see below for supported values character (len = *), intent(in), optional :: name character (len = *), intent(in), optional :: convention character (len = *), intent(in), optional :: purpose character (len = *), intent(in), optional :: attPackInstanceName integer, intent(out), optional :: rcDESCRIPTION:
Remove an Attribute, or Attribute package on <object>. See Section 36.2 for a description of Attribute packages and their conventions, purposes, and object types.
Supported values for <object> are:
The arguments are:
NOTE: An entire Attribute package can be removed by specifying convention and purpose only, without name. By specifying convention, purpose, and name an Attribute will be removed from the corresponding Attribute package, if it exists. An Attribute can be removed directly from <object> by specifying name, without convention and purpose.
INTERFACE:
subroutine ESMF_AttributeSet(<object>, name, <value argument>, & convention, purpose, attPackInstanceName, rc)ARGUMENTS:
<object>, see below for supported values character (len = *), intent(in) :: name <value argument>, see below for supported values character (len = *), intent(in), optional :: convention character (len = *), intent(in), optional :: purpose character (len = *), intent(in), optional :: attPackInstanceName integer, intent(out), optional :: rcDESCRIPTION:
Attach an Attribute to <object>, or set an Attribute in an Attribute package. The Attribute has a name and value, and, if in an Attribute package, a convention and purpose, and optionally an attPackInstanceName. See Section 36.2 for a description of Attribute packages and their conventions, purposes, and object types.
Supported values for <object> are:
The arguments are:
INTERFACE:
subroutine ESMF_AttributeSet(<object>, name, <valueList argument>, & convention, purpose, attPackInstanceName, & itemCount, rc)ARGUMENTS:
<object>, see below for supported values character (len = *), intent(in) :: name <valueList argument>, see below for supported values character (len = *), intent(in), optional :: convention character (len = *), intent(in), optional :: purpose character (len = *), intent(in), optional :: attPackInstanceName integer, intent(in), optional :: itemCount integer, intent(out), optional :: rcDESCRIPTION:
Attach an Attribute to <object>, or set an Attribute in an Attribute package. The Attribute has a name and a valueList, with an itemCount, and, if in an Attribute package, a convention and purpose, and optionally an attPackInstanceName. See Section 36.2 for a description of Attribute packages and their conventions, purposes, and object types.
Supported values for <object> are:
The arguments are:
INTERFACE:
subroutine ESMF_AttributeUpdate(<object>, vm, rootList, rc)ARGUMENTS:
<object>, see below for supported values type(ESMF_VM), intent(in) :: vm integer, intent(in) :: rootList(:) integer, intent(out), optional :: rcDESCRIPTION:
Update an Attribute hierarchy during runtime. This call will not work if changes have been made to the underlying object hierarchy and ESMF_StateReconcile() has not already been called. There is a check that will fail if this case is encountered. The information from the PETs in the 'rootList' is transferred to the PETs that are not in the 'rootList'. Care should be taken to ensure that the information contained in the Attributes on the PETs in the 'rootList' is consistent.
Supported values for <object> are:
The arguments are:
INTERFACE:
subroutine ESMF_AttributeWrite(<object>, convention, purpose, & attwriteflag, rc)ARGUMENTS:
<object>, see below for supported values character (len = *), intent(in), optional :: convention character (len = *), intent(in), optional :: purpose type(ESMF_AttWriteFlag), intent(in), optional :: attwriteflag integer, intent(out), optional :: rcDESCRIPTION:
Write the Attribute package for <object>. The Attribute package defines the convention, purpose, and object type of the associated Attributes. Either tab-delimited or xml format is acheived by using attwriteflag. Currently, only ESMF/ESG/CF Field Attribute packages can be written in tab-delimited format. See Section 36.2 for a description of Attribute packages and their conventions, purposes, and object types.
Writing Attribute XML files is performed with the standard C++ output file stream facility.
Note: For an object type of ESMF_GridComp, convention='WaterML',
purpose='TimeSeries', and
attwriteflag=ESMF_ATTWRITE_XML, an XML file
conforming to a hydrologic standard called WaterML will be written. See
the following for more information:
An ESMF Use Test Case is available which showcases an example of how to write a WaterML file; please see
Supported values for <object> are:
The arguments are:
The ESMF Time Manager utility includes software for time and date representation and calculations, model time advancement, and the identification of unique and periodic events. Since multi-component geophysical applications often require synchronization across the time management schemes of the individual components, the Time Manager's standard calendars and consistent time representation promote component interoperability.
Key Features |
Drift-free timekeeping through an integer-based internal time representation. Both integers and reals can be specified at the interface. |
The ability to represent time as a rational fraction, to support exact timekeeping in applications that involve grid refinement. |
Support for many calendar kinds, including user-customized calendars. |
Support for both concurrent and sequential modes of component execution. |
Support for varying and negative time steps. |
In the remainder of this section, we briefly summarize the functionality that the Time Manager classes provide. Detailed descriptions and usage examples precede the API listing for each class.
TimeIntervals and Time instants (simply called Times) are the computational building blocks of the Time Manager utility. TimeIntervals support operations such as add, subtract, compare size, reset value, copy value, and subdivide by a scalar. Times, which are moments in time associated with specific Calendars, can be incremented or decremented by TimeIntervals, compared to determine which of two Times is later, differenced to obtain the TimeInterval between two Times, copied, reset, and manipulated in other useful ways. Times support a host of different queries, both for values of individual Time components such as year, month, day, and second, and for derived values such as day of year, middle of current month and Julian day. It is also possible to retrieve the value of the hardware realtime clock in the form of a Time. See Sections 39.1 and 40.1, respectively, for use and examples of Times and TimeIntervals.
Since climate modeling, numerical weather prediction and other Earth and space applications have widely varying time scales and require different sorts of calendars, Times and TimeIntervals must support a wide range of time specifiers, spanning nanoseconds to years. The interfaces to these time classes are defined so that the user can specify a time using a combination of units selected from the list shown in Table 37.4.
Unit | Meaning |
<yy|yy_i8> | Year. |
mm | Month of the year. |
dd | Day of the month. |
<d|d_i8|d_r8> | Julian or Modified Julian day. |
<h|h_r8> | Hour. |
<m|m_r8> | Minute. |
<s|s_i8|s_r8> | Second. |
<ms|ms_r8> | Millisecond. |
<us|us_r8> | Microsecond. |
<ns|ns_r8> | Nanosecond. |
O | Time zone offset in integer number of hours and minutes. |
<sN|sN_i8> | Numerator for times of the form s , where s is seconds and s, sN, and sD are integers. This format provides a mechanism for supporting exact behavior. |
<sD|sD_i8 | Denominator for times of the form s , where s is seconds and s, sN, and sD are integers. |
The result of this strategy is that Time Intervals and Times gain a consistent core representation of time as well a set of basic methods.
The BaseTime class can be designed with a minimum number of elements to represent any required time. The design is based on the idea used in the real-time POSIX 1003.1b-1993 standard. That is, to represent time simply as a pair of integers: one for seconds (whole) and one for nanoseconds (fractional). These can then be converted at the interface level to any desired format.
For ESMF, this idea can be modified and extended, in order to handle the requirements for a large time range (> 200,000 years) and to exactly represent any rational fraction, not just nanoseconds. To handle the large time range, a 64-bit or greater integer is used for whole seconds. Any rational fractional second is expressed using two additional integers: a numerator and a denominator. Both the whole seconds and fractional numerator are signed to handle negative time intervals and instants. For arithmetic consistency both must carry the same sign (both positve or both negative), except, of course, for zero values. The fractional seconds element (numerator) is bounded with respect to whole seconds. If the absolute value of the numerator becomes greater than or equal to the denominator, whole seconds are incremented or decremented accordingly and the numerator is reset to the remainder. Conversions are performed upon demand by interface methods within the TimeInterval and Time classes. This is done because different applications require different representations of time intervals and time instances. Floating point values as well as integers can be specified for the various time units in the interfaces, see Table 37.4. Floating point values are represented internally as integer-based rational fractions.
The BaseTime class defines increment and decrement methods for basic TimeInterval calculations between Time instants. It is done here rather than in the Calendar class because it can be done with simple second-based arithmetic that is calendar independent.
Comparison methods can also be defined in the BaseTime class. These perform equality/inequality, less than, and greater than comparisons between any two TimeIntervals or Times. These methods capture the common comparison logic between TimeIntervals and Times and hence are defined here for sharing.
The following is a simplified UML diagram showing the structure of the Time Manager utility. See Appendix A, A Brief Introduction to UML, for a translation table that lists the symbols in the diagram and their meaning.
The Calendar class represents the standard calendars used in geophysical modeling: Gregorian, Julian, Julian Day, Modified Julian Day, no-leap, 360-day, and no-calendar. It also supports a user-customized calendar. Brief descriptions are provided for each calendar below. For more information on standard calendars, see [22] and [16].
DESCRIPTION:
Supported calendar kinds.
The type of this flag is:
type(ESMF_CalKind_Flag)
The valid values are:
MJD = JD - 2400000.5
The half day is subtracted so that the day starts at midnight.
In most multi-component Earth system applications, the timekeeping in each component must refer to the same standard calendar in order for the components to properly synchronize. It therefore makes sense to create as few ESMF Calendars as possible, preferably one per application. A typical strategy would be to create a single Calendar at the start of an application, and use that Calendar in all subsequent calls that accept a Calendar, such as ESMF_TimeSet.
The following example shows how to set up an ESMF Calendar.
! !PROGRAM: ESMF_CalendarEx - Calendar creation examples ! ! !DESCRIPTION: ! ! This program shows examples of how to create different calendar kinds !----------------------------------------------------------------------------- #include "ESMF.h" ! ESMF Framework module use ESMF use ESMF_TestMod implicit none ! instantiate calendars type(ESMF_Calendar) :: gregorianCalendar type(ESMF_Calendar) :: julianDayCalendar type(ESMF_Calendar) :: marsCalendar ! local variables for Get methods integer :: sols integer(ESMF_KIND_I8) :: dl type(ESMF_Time) :: time, marsTime type(ESMF_TimeInterval) :: marsTimeStep ! return code integer:: rc
! initialize ESMF framework call ESMF_Initialize(defaultlogfilename="CalendarEx.Log", & logkindflag=ESMF_LOGKIND_MULTI, rc=rc)
This example shows how to create three ESMF_Calendars.
! create a Gregorian calendar gregorianCalendar = ESMF_CalendarCreate(ESMF_CALKIND_GREGORIAN, & name="Gregorian", rc=rc)
! create a Julian Day calendar julianDayCalendar = ESMF_CalendarCreate(ESMF_CALKIND_JULIANDAY, & name="JulianDay", rc=rc)
! create a Custom calendar for the planet Mars ! 1 Mars solar day = 24 hours, 39 minutes, 35 seconds = 88775 seconds ! 1 Mars solar year = 668.5921 Mars solar days = 668 5921/10000 sols/year ! http://www.giss.nasa.gov/research/briefs/allison_02 ! http://www.giss.nasa.gov/tools/mars24/help/notes.html marsCalendar = ESMF_CalendarCreate(secondsPerDay=88775, & daysPerYear=668, & daysPerYearDn=5921, & daysPerYearDd=10000, & name="MarsCalendar", rc=rc)
This example shows how to compare an ESMF_Calendar with a known calendar kind.
! compare calendar kind against a known type if (gregorianCalendar == ESMF_CALKIND_GREGORIAN) then print *, "gregorianCalendar is of type ESMF_CALKIND_GREGORIAN." else print *, "gregorianCalendar is not of type ESMF_CALKIND_GREGORIAN." end if
This example shows how to convert a time from one ESMF_Calendar to another.
call ESMF_TimeSet(time, yy=2004, mm=4, dd=17, & calendar=gregorianCalendar, rc=rc)
! switch time's calendar to perform conversion call ESMF_TimeSet(time, calendar=julianDayCalendar, rc=rc)
call ESMF_TimeGet(time, d_i8=dl, rc=rc) print *, "Gregorian date 2004/4/17 is ", dl, & " days in the Julian Day calendar."
This example shows how to increment a time using a custom ESMF_Calendar.
! Set a time to Mars solar year 3, sol 100 call ESMF_TimeSet(marsTime, yy=3, d=100, & calendar=marsCalendar, rc=rc)
! Set a 1 solar year time step call ESMF_TimeIntervalSet(marsTimeStep, yy=1, rc=rc)
! Perform the increment marsTime = marsTime + marsTimeStep
! Get the result in sols (2774 = (3+1)*668.5921 + 100) call ESMF_TimeGet(marsTime, d=sols, rc=rc) print *, "For Mars, 3 solar years, 100 sols + 1 solar year = ", & sols, "sols."
This example shows how to destroy three ESMF_Calendars.
call ESMF_CalendarDestroy(julianDayCalendar, rc=rc)
call ESMF_CalendarDestroy(gregorianCalendar, rc=rc)
call ESMF_CalendarDestroy(marsCalendar, rc=rc)
! finalize ESMF framework call ESMF_Finalize(rc=rc)
end program ESMF_CalendarEx
INTERFACE:
interface assignment(=) calendar1 = calendar2ARGUMENTS:
type(ESMF_Calendar) :: calendar1 type(ESMF_Calendar) :: calendar2STATUS:
DESCRIPTION:
Assign calendar1 as an alias to the same ESMF_Calendar object in memory as calendar2. If calendar2 is invalid, then calendar1 will be equally invalid after the assignment.
The arguments are:
INTERFACE:
interface operator(==) if (<calendar argument 1> == <calendar argument 2>) then ... endif OR result = (<calendar argument 1> == <calendar argument 2>)RETURN VALUE:
logical :: resultARGUMENTS:
<calendar argument 1>, see below for supported values <calendar argument 2>, see below for supported valuesDESCRIPTION:
Overloads the (==) operator for the ESMF_Calendar class. Compare an ESMF_Calendar object or ESMF_CalKind_Flag with another calendar object or calendar kind for equality. Return .true. if equal, .false. otherwise. Comparison is based on calendar kind, which is a property of a calendar object.
If both arguments are ESMF_Calendar objects, and both are of type ESMF_CALKIND_CUSTOM, then all the calendar's properties, except name, are compared.
If both arguments are ESMF_Calendar objects, and either of them is not in the ESMF_INIT_CREATED status, an error will be logged. However, this does not affect the return value, which is .true. when both arguments are in the same status, and .false. otherwise.
If one argument is an ESMF_Calendar object, and the other is an ESMF_CalKind_Flag, and the calendar object is not in the ESMF_INIT_CREATED status, an error will be logged and .false. will be returned.
Supported values for <calendar argument 1> are:
The arguments are:
INTERFACE:
interface operator(/=) if (<calendar argument 1> /= <calendar argument 2>) then ... endif OR result = (<calendar argument 1> /= <calendar argument 2>)RETURN VALUE:
logical :: resultARGUMENTS:
<calendar argument 1>, see below for supported values <calendar argument 2>, see below for supported valuesDESCRIPTION:
Overloads the (/=) operator for the ESMF_Calendar class. Compare a ESMF_Calendar object or ESMF_CalKind_Flag with another calendar object or calendar kind for inequality. Return .true. if not equal, .false. otherwise. Comparison is based on calendar kind, which is a property of a calendar object.
If both arguments are ESMF_Calendar objects, and both are of type ESMF_CALKIND_CUSTOM, then all the calendar's properties, except name, are compared.
If both arguments are ESMF_Calendar objects, and either of them is not in the ESMF_INIT_CREATED status, an error will be logged. However, this does not affect the return value, which is .true. when both arguments are not in the same status, and .false. otherwise.
If one argument is an ESMF_Calendar object, and the other is an ESMF_CalKind_Flag, and the calendar object is not in the ESMF_INIT_CREATED status, an error will be logged and .true. will be returned.
Supported values for <calendar argument 1> are:
The arguments are:
INTERFACE:
! Private name; call using ESMF_CalendarCreate() function ESMF_CalendarCreateBuiltIn(calkindflag, & name, rc)RETURN VALUE:
type(ESMF_Calendar) :: ESMF_CalendarCreateBuiltInARGUMENTS:
type(ESMF_CalKind_Flag), intent(in) :: calkindflag -- The following arguments require argument keyword syntax (e.g. rc=rc). -- character (len=*), intent(in), optional :: name integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Creates and sets a calendar to the given built-in ESMF_CalKind_Flag.
The arguments are:
INTERFACE:
! Private name; call using ESMF_CalendarCreate() function ESMF_CalendarCreateCopy(calendar, rc)RETURN VALUE:
type(ESMF_Calendar) :: ESMF_CalendarCreateCopyARGUMENTS:
type(ESMF_Calendar), intent(in) :: calendar -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Creates a complete (deep) copy of a given ESMF_Calendar.
The arguments are:
INTERFACE:
! Private name; call using ESMF_CalendarCreate() function ESMF_CalendarCreateCustom(& daysPerMonth, secondsPerDay, & daysPerYear, daysPerYearDn, daysPerYearDd, name, rc)RETURN VALUE:
type(ESMF_Calendar) :: ESMF_CalendarCreateCustomARGUMENTS:
-- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(in), optional :: daysPerMonth(:) integer(ESMF_KIND_I4), intent(in), optional :: secondsPerDay integer(ESMF_KIND_I4), intent(in), optional :: daysPerYear integer(ESMF_KIND_I4), intent(in), optional :: daysPerYearDn integer(ESMF_KIND_I4), intent(in), optional :: daysPerYearDd character (len=*), intent(in), optional :: name integer, intent(out), optional :: rcDESCRIPTION:
Creates a custom ESMF_Calendar and sets its properties.
The arguments are:
INTERFACE:
subroutine ESMF_CalendarDestroy(calendar, rc)ARGUMENTS:
type(ESMF_Calendar), intent(inout) :: calendar -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Releases resources associated with this ESMF_Calendar.
The arguments are:
INTERFACE:
subroutine ESMF_CalendarGet(calendar, & name, calkindflag, daysPerMonth, monthsPerYear, & secondsPerDay, secondsPerYear, & daysPerYear, daysPerYearDn, daysPerYearDd, rc)ARGUMENTS:
type(ESMF_Calendar), intent(in) :: calendar -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_CalKind_Flag),intent(out), optional :: calkindflag integer, intent(out), optional :: daysPerMonth(:) integer, intent(out), optional :: monthsPerYear integer(ESMF_KIND_I4), intent(out), optional :: secondsPerDay integer(ESMF_KIND_I4), intent(out), optional :: secondsPerYear integer(ESMF_KIND_I4), intent(out), optional :: daysPerYear integer(ESMF_KIND_I4), intent(out), optional :: daysPerYearDn integer(ESMF_KIND_I4), intent(out), optional :: daysPerYearDd character (len=*), intent(out), optional :: name integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Gets one or more of an ESMF_Calendar's properties.
The arguments are:
INTERFACE:
! Private name; call using ESMF_CalendarIsLeapYear() function ESMF_CalendarIsLeapYear<kind>(calendar, yy, rc)RETURN VALUE:
logical :: ESMF_CalendarIsLeapYear<kind>ARGUMENTS:
type(ESMF_Calendar), intent(in) :: calendar integer(ESMF_KIND_<kind>), intent(in) :: yy -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Returns .true. if the given year is a leap year within the given calendar, and .false. otherwise. Custom calendars do not define leap years, so .false. will always be returned in this case; see Section 38.4. See also ESMF_TimeIsLeapYear().
The arguments are:
INTERFACE:
subroutine ESMF_CalendarPrint(calendar, options, rc)ARGUMENTS:
type(ESMF_Calendar), intent(in) :: calendar character (len=*), intent(in), optional :: options integer, intent(out), optional :: rcDESCRIPTION:
Prints out an ESMF_Calendar's properties to stdio,
in support of testing and debugging. The options control the
type of information and level of detail.
The arguments are:
INTERFACE:
! Private name; call using ESMF_CalendarSet() subroutine ESMF_CalendarSetBuiltIn(calendar, calkindflag, & name, rc)ARGUMENTS:
type(ESMF_Calendar), intent(inout) :: calendar type(ESMF_CalKind_Flag), intent(in) :: calkindflag -- The following arguments require argument keyword syntax (e.g. rc=rc). -- character (len=*), intent(in), optional :: name integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Sets calendar to the given built-in ESMF_CalKind_Flag.
The arguments are:
INTERFACE:
! Private name; call using ESMF_CalendarSet() subroutine ESMF_CalendarSetCustom(calendar, & daysPerMonth, secondsPerDay, & daysPerYear, daysPerYearDn, daysPerYearDd, name, rc)ARGUMENTS:
type(ESMF_Calendar), intent(inout) :: calendar -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(in), optional :: daysPerMonth(:) integer(ESMF_KIND_I4),intent(in), optional :: secondsPerDay integer(ESMF_KIND_I4),intent(in), optional :: daysPerYear integer(ESMF_KIND_I4),intent(in), optional :: daysPerYearDn integer(ESMF_KIND_I4),intent(in), optional :: daysPerYearDd character (len=*), intent(in), optional :: name integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Sets properties in a custom ESMF_Calendar.
The arguments are:
INTERFACE:
! Private name; call using ESMF_CalendarSetDefault() subroutine ESMF_CalendarSetDefaultKind(calkindflag, rc)ARGUMENTS:
type(ESMF_CalKind_Flag), intent(in) :: calkindflag integer, intent(out), optional :: rcDESCRIPTION:
Sets the default calendar to the given type. Subsequent Time Manager operations requiring a calendar where one isn't specified will use the internal calendar of this type.
The arguments are:
INTERFACE:
! Private name; call using ESMF_CalendarSetDefault() subroutine ESMF_CalendarSetDefaultCal(calendar, rc)ARGUMENTS:
type(ESMF_Calendar), intent(in) :: calendar integer, intent(out), optional :: rcDESCRIPTION:
Sets the default calendar to the one given. Subsequent Time Manager operations requiring a calendar where one isn't specified will use this calendar.
The arguments are:
INTERFACE:
subroutine ESMF_CalendarValidate(calendar, rc)ARGUMENTS:
type(ESMF_Calendar), intent(in) :: calendar -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Checks whether a calendar is valid. Must be one of the defined calendar kinds. daysPerMonth, daysPerYear, secondsPerDay must all be greater than or equal to zero.
The arguments are:
A Time represents a specific point in time. In order to accommodate the range of time scales in Earth system applications, Times in the ESMF an be specified in many different ways, from years to nanoseconds. The Time interface is designed so that you select one or more options from a list of time units in order to specify a Time. The options for specifying a Time are shown in Table 37.4.
There are Time methods defined for setting and getting a Time, incrementing and decrementing a Time by a TimeInterval, taking the difference between two Times, and comparing Times. Special quantities such as the middle of the month and the day of the year associated with a particular Time can be retrieved. There is a method for returning the Time value as a string in the ISO 8601 format YYYY-MM-DDThh:mm:ss [13].
A Time that is specified in hours, minutes, seconds, or subsecond intervals does not need to be associated with a standard calendar; a Time whose specification includes time units of a day and greater must be. The ESMF representation of a calendar, the Calendar class, is described in Section 38.1. The ESMF_TimeSet method is used to initialize a Time as well as associate it with a Calendar. If a Time method is invoked in which a Calendar is necessary and one has not been set, the ESMF method will return an error condition.
In the ESMF the TimeInterval class is used to represent time periods. This class is frequently used in combination with the Time class. The Clock class, for example, advances model time by incrementing a Time with a TimeInterval.
Times are most frequently used to represent start, stop, and current model times. The following examples show how to create, initialize, and manipulate Time.
! !PROGRAM: ESMF_TimeEx - Time initialization and manipulation examples ! ! !DESCRIPTION: ! ! This program shows examples of Time initialization and manipulation !----------------------------------------------------------------------------- #include "ESMF.h" ! ESMF Framework module use ESMF use ESMF_TestMod implicit none ! instantiate two times type(ESMF_Time) :: time1, time2 type(ESMF_VM) :: vm ! instantiate a time interval type(ESMF_TimeInterval) :: timeinterval1 ! local variables for Get methods integer :: YY, MM, DD, H, M, S ! return code integer:: rc
! initialize ESMF framework call ESMF_Initialize(vm=vm, defaultCalKind=ESMF_CALKIND_GREGORIAN, & defaultlogfilename="TimeEx.Log", & logkindflag=ESMF_LOGKIND_MULTI, rc=rc)
This example shows how to initialize an ESMF_Time.
! initialize time1 to 2/28/2000 2:24:45 call ESMF_TimeSet(time1, yy=2000, mm=2, dd=28, h=2, m=24, s=45, rc=rc)
print *, "Time1 = " call ESMF_TimePrint(time1, options="string", rc=rc)
This example shows how to increment an ESMF_Time by an ESMF_TimeInterval.
! initialize a time interval to 2 days, 8 hours, 36 minutes, 15 seconds call ESMF_TimeIntervalSet(timeinterval1, d=2, h=8, m=36, s=15, rc=rc)
print *, "Timeinterval1 = " call ESMF_TimeIntervalPrint(timeinterval1, options="string", rc=rc)
! increment time1 with timeinterval1 time2 = time1 + timeinterval1 call ESMF_TimeGet(time2, yy=YY, mm=MM, dd=DD, h=H, m=M, s=S, rc=rc) print *, "time2 = time1 + timeinterval1 = ", YY, "/", MM, "/", DD, & " ", H, ":", M, ":", S
This example shows how to compare two ESMF_Times.
if (time2 > time1) then print *, "time2 is larger than time1" else print *, "time1 is smaller than or equal to time2" endif
! finalize ESMF framework call ESMF_Finalize(rc=rc)
end program ESMF_TimeEx
For fractional seconds, a signed 64-bit integer will handle a resolution of +/- -1, or +/- 9,223,372,036,854,775,807 parts of a second.
INTERFACE:
interface assignment(=) time1 = time2ARGUMENTS:
type(ESMF_Time) :: time1 type(ESMF_Time) :: time2STATUS:
DESCRIPTION:
Set time1 equal to time2. This is the default Fortran assignment, which creates a complete, independent copy of time2 as time1. If time2 is an invalid ESMF_Time object then time1 will be equally invalid after the assignment.
The arguments are:
INTERFACE:
interface operator(+) time2 = time1 + timeintervalRETURN VALUE:
type(ESMF_Time) :: time2ARGUMENTS:
type(ESMF_Time), intent(in) :: time1 type(ESMF_TimeInterval), intent(in) :: timeintervalSTATUS:
DESCRIPTION:
Overloads the (+) operator for the ESMF_Time class to increment time1 with timeinterval and return the result as an ESMF_Time.
The arguments are:
INTERFACE:
interface operator(-) time2 = time1 - timeintervalRETURN VALUE:
type(ESMF_Time) :: time2ARGUMENTS:
type(ESMF_Time), intent(in) :: time1 type(ESMF_TimeInterval), intent(in) :: timeintervalSTATUS:
DESCRIPTION:
Overloads the (-) operator for the ESMF_Time class to decrement time1 with timeinterval, and return the result as an ESMF_Time.
The arguments are:
INTERFACE:
interface operator(-) time3 = time1 - time2RETURN VALUE:
type(ESMF_Time) :: time3ARGUMENTS:
type(ESMF_Time), intent(in) :: time1 type(ESMF_Time), intent(in) :: time2STATUS:
DESCRIPTION:
Overloads the (-) operator for the ESMF_Time class to return the difference between time1 and time2 as an ESMF_TimeInterval. It is assumed that time1 is later than time2; if not, the resulting ESMF_TimeInterval will have a negative value.
The arguments are:
INTERFACE:
interface operator(==) if (time1 == time2) then ... endif OR result = (time1 == time2)RETURN VALUE:
logical :: resultARGUMENTS:
type(ESMF_Time), intent(in) :: time1 type(ESMF_Time), intent(in) :: time2STATUS:
DESCRIPTION:
Overloads the (==) operator for the ESMF_Time class to return .true. if time1 and time2 represent the same instant in time, and .false. otherwise.
The arguments are:
INTERFACE:
interface operator(/=) if (time1 /= time2) then ... endif OR result = (time1 /= time2)RETURN VALUE:
logical :: resultARGUMENTS:
type(ESMF_Time), intent(in) :: time1 type(ESMF_Time), intent(in) :: time2STATUS:
DESCRIPTION:
Overloads the (/=) operator for the ESMF_Time class to return .true. if time1 and time2 do not represent the same instant in time, and .false. otherwise.
The arguments are:
INTERFACE:
interface operator(<) if (time1 < time2) then ... endif OR result = (time1 < time2)RETURN VALUE:
logical :: resultARGUMENTS:
type(ESMF_Time), intent(in) :: time1 type(ESMF_Time), intent(in) :: time2STATUS:
DESCRIPTION:
Overloads the (<) operator for the ESMF_Time class to return .true. if time1 is earlier in time than time2, and .false. otherwise.
The arguments are:
INTERFACE:
interface operator(<=) if (time1 <= time2) then ... endif OR result = (time1 <= time2)RETURN VALUE:
logical :: resultARGUMENTS:
type(ESMF_Time), intent(in) :: time1 type(ESMF_Time), intent(in) :: time2STATUS:
DESCRIPTION:
Overloads the (<=) operator for the ESMF_Time class to return .true. if time1 is earlier in time or the same time as time2, and .false. otherwise.
The arguments are:
INTERFACE:
interface operator(>) if (time1 > time2) then ... endif OR result = (time1 > time2)RETURN VALUE:
logical :: resultARGUMENTS:
type(ESMF_Time), intent(in) :: time1 type(ESMF_Time), intent(in) :: time2STATUS:
DESCRIPTION:
Overloads the (>) operator for the ESMF_Time class to return .true. if time1 is later in time than time2, and .false. otherwise.
The arguments are:
INTERFACE:
interface operator(>=) if (time1 >= time2) then ... endif OR result = (time1 >= time2)RETURN VALUE:
logical :: resultARGUMENTS:
type(ESMF_Time), intent(in) :: time1 type(ESMF_Time), intent(in) :: time2STATUS:
DESCRIPTION:
Overloads the (>=) operator for the ESMF_Time class to return .true. if time1 is later in time or the same time as time2, and .false. otherwise.
The arguments are:
INTERFACE:
subroutine ESMF_TimeGet(time, & yy, yy_i8, & mm, dd, & d, d_i8, & h, m, & s, s_i8, & ms, us, ns, & d_r8, h_r8, m_r8, s_r8, & ms_r8, us_r8, ns_r8, & sN, sN_i8, sD, sD_i8, & calendar, calkindflag, timeZone, & timeString, timeStringISOFrac, & dayOfWeek, midMonth, & dayOfYear, dayOfYear_r8, & dayOfYear_intvl, rc)ARGUMENTS:
type(ESMF_Time), intent(in) :: time -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer(ESMF_KIND_I4), intent(out), optional :: yy integer(ESMF_KIND_I8), intent(out), optional :: yy_i8 integer, intent(out), optional :: mm integer, intent(out), optional :: dd integer(ESMF_KIND_I4), intent(out), optional :: d integer(ESMF_KIND_I8), intent(out), optional :: d_i8 integer(ESMF_KIND_I4), intent(out), optional :: h integer(ESMF_KIND_I4), intent(out), optional :: m integer(ESMF_KIND_I4), intent(out), optional :: s integer(ESMF_KIND_I8), intent(out), optional :: s_i8 integer(ESMF_KIND_I4), intent(out), optional :: ms integer(ESMF_KIND_I4), intent(out), optional :: us integer(ESMF_KIND_I4), intent(out), optional :: ns real(ESMF_KIND_R8), intent(out), optional :: d_r8 real(ESMF_KIND_R8), intent(out), optional :: h_r8 real(ESMF_KIND_R8), intent(out), optional :: m_r8 real(ESMF_KIND_R8), intent(out), optional :: s_r8 real(ESMF_KIND_R8), intent(out), optional :: ms_r8 real(ESMF_KIND_R8), intent(out), optional :: us_r8 real(ESMF_KIND_R8), intent(out), optional :: ns_r8 integer(ESMF_KIND_I4), intent(out), optional :: sN integer(ESMF_KIND_I8), intent(out), optional :: sN_i8 integer(ESMF_KIND_I4), intent(out), optional :: sD integer(ESMF_KIND_I8), intent(out), optional :: sD_i8 type(ESMF_Calendar), intent(out), optional :: calendar type(ESMF_CalKind_Flag), intent(out), optional :: calkindflag integer, intent(out), optional :: timeZone ! not imp character (len=*), intent(out), optional :: timeString character (len=*), intent(out), optional :: timeStringISOFrac integer, intent(out), optional :: dayOfWeek type(ESMF_Time), intent(out), optional :: midMonth integer(ESMF_KIND_I4), intent(out), optional :: dayOfYear real(ESMF_KIND_R8), intent(out), optional :: dayOfYear_r8 type(ESMF_TimeInterval), intent(out), optional :: dayOfYear_intvl integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Gets the value of time in units specified by the user via Fortran optional arguments. See ESMF_TimeSet() above for a description of time units and calendars.
The ESMF Time Manager represents and manipulates time internally with integers to maintain precision. Hence, user-specified floating point values are converted internally from integers. For example, if a time value is 5 and 3/8 seconds (s=5, sN=3, sD=8), and you want to get it as floating point seconds, you would get 5.375 (s_r8=5.375).
Units are bound (normalized) by the next larger unit specified. For example, if a time is defined to be 2:00 am on February 2, 2004, then ESMF_TimeGet(dd=day, h=hours, s=seconds) would return day = 2, hours = 2, seconds = 0, whereas ESMF_TimeGet(dd = day, s=seconds) would return day = 2, seconds = 7200. Note that hours and seconds are bound by a day. If bound by a month, ESMF_TimeGet(mm=month, h=hours, s=seconds) would return month = 2, hours = 26, seconds = 0, and ESMF_TimeGet(mm = month, s=seconds) would return month = 2, seconds = 93600 (26 * 3600). Similarly, if bound to a year, ESMF_TimeGet(yy=year, h=hours, s=seconds) would return year = 2004, hours = 770 (32*24 + 2), seconds = 0, and ESMF_TimeGet(yy = year, s=seconds) would return year = 2004, seconds = 2772000 (770 * 3600).
For timeString, timeStringISOFrac, dayOfWeek,
midMonth, dayOfYear, dayOfYear_intvl, and
dayOfYear_r8 described below, valid calendars are Gregorian,
Julian, No Leap, 360 Day and Custom calendars. Not valid for
Julian Day, Modified Julian Day, or No Calendar.
For timeString and timeStringISOFrac, YYYY format returns at least 4 digits; years <= 999 are padded on the left with zeroes and years >= 10000 return the number of digits required.
For timeString, convert ESMF_Time's value into partial ISO 8601 format YYYY-MM-DDThh:mm:ss[:n/d]. See [13] and [2]. See also method ESMF_TimePrint().
For timeStringISOFrac, convert ESMF_Time's value into full ISO 8601 format YYYY-MM-DDThh:mm:ss[.f]. See [13] and [2]. See also method ESMF_TimePrint().
For dayOfWeek, gets the day of the week the given ESMF_Time instant falls on. ISO 8601 standard: Monday = 1 through Sunday = 7. See [13] and [2].
For midMonth, gets the middle time instant of the month that the given ESMF_Time instant falls on.
For dayOfYear, gets the day of the year that the given ESMF_Time instant falls on. See range discussion in argument list below. Return as an integer value.
For dayOfYear_r8, gets the day of the year the given ESMF_Time instant falls on. See range discussion in argument list below. Return as floating point value; fractional part represents the time of day.
For dayOfYear_intvl, gets the day of the year the given ESMF_Time instant falls on. Return as an ESMF_TimeInterval.
The arguments are:
INTERFACE:
function ESMF_TimeIsLeapYear(time, rc)RETURN VALUE:
logical :: ESMF_TimeIsLeapYearARGUMENTS:
type(ESMF_Time), intent(in) :: time -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Returns .true. if given time is in a leap year, and .false. otherwise. See also ESMF_CalendarIsLeapYear().
The arguments are:
INTERFACE:
function ESMF_TimeIsSameCalendar(time1, time2, rc)RETURN VALUE:
logical :: ESMF_TimeIsSameCalendarARGUMENTS:
type(ESMF_Time), intent(in) :: time1 type(ESMF_Time), intent(in) :: time2 -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Returns .true. if the Calendars in these Times are the same, .false. otherwise.
The arguments are:
INTERFACE:
subroutine ESMF_TimePrint(time, options, rc)ARGUMENTS:
type(ESMF_Time), intent(in) :: time character (len=*), intent(in), optional :: options integer, intent(out), optional :: rcDESCRIPTION:
Prints out the contents of an ESMF_Time to stdout, in
support of testing and debugging. The options control the type of
information and level of detail. For options "string" and "string
isofrac", YYYY format returns at least 4 digits; years <= 999 are
padded on the left with zeroes and years >= 10000 return the number
of digits required.
The arguments are:
INTERFACE:
subroutine ESMF_TimeSet(time, & yy, yy_i8, & mm, dd, & d, d_i8, & h, m, & s, s_i8, & ms, us, ns, & d_r8, h_r8, m_r8, s_r8, & ms_r8, us_r8, ns_r8, & sN, sN_i8, sD, sD_i8, & calendar, calkindflag, & timeZone, rc)ARGUMENTS:
type(ESMF_Time), intent(inout) :: time -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer(ESMF_KIND_I4), intent(in), optional :: yy integer(ESMF_KIND_I8), intent(in), optional :: yy_i8 integer, intent(in), optional :: mm integer, intent(in), optional :: dd integer(ESMF_KIND_I4), intent(in), optional :: d integer(ESMF_KIND_I8), intent(in), optional :: d_i8 integer(ESMF_KIND_I4), intent(in), optional :: h integer(ESMF_KIND_I4), intent(in), optional :: m integer(ESMF_KIND_I4), intent(in), optional :: s integer(ESMF_KIND_I8), intent(in), optional :: s_i8 integer(ESMF_KIND_I4), intent(in), optional :: ms integer(ESMF_KIND_I4), intent(in), optional :: us integer(ESMF_KIND_I4), intent(in), optional :: ns real(ESMF_KIND_R8), intent(in), optional :: d_r8 real(ESMF_KIND_R8), intent(in), optional :: h_r8 real(ESMF_KIND_R8), intent(in), optional :: m_r8 real(ESMF_KIND_R8), intent(in), optional :: s_r8 real(ESMF_KIND_R8), intent(in), optional :: ms_r8 real(ESMF_KIND_R8), intent(in), optional :: us_r8 real(ESMF_KIND_R8), intent(in), optional :: ns_r8 integer(ESMF_KIND_I4), intent(in), optional :: sN integer(ESMF_KIND_I8), intent(in), optional :: sN_i8 integer(ESMF_KIND_I4), intent(in), optional :: sD integer(ESMF_KIND_I8), intent(in), optional :: sD_i8 type(ESMF_Calendar), intent(in), optional :: calendar type(ESMF_CalKind_Flag), intent(in), optional :: calkindflag integer, intent(in), optional :: timeZone ! not imp integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Initializes an ESMF_Time with a set of user-specified units via Fortran optional arguments.
The range of valid values for mm and dd depend on the calendar used. For Gregorian, Julian, and No-Leap calendars, mm is [1-12] and dd is [1-28,29,30, or 31], depending on the value of mm and whether yy or yy_i8 is a leap year. For the 360-day calendar, mm is [1-12] and dd is [1-30]. For Julian Day, Modified Julian Day, and No-Calendar, yy, yy_i8, mm, and dd are invalid inputs, since these calendars do not define them. When valid, the yy and yy_i8 arguments should be fully specified, e.g. 2003 instead of 03. yy and yy_i8 ranges are only limited by machine word size, except for the Gregorian and Julian calendars, where the lowest (proleptic) date limits are 3/1/-4800 and 3/1/-4712, respectively. This is a limitation of the Gregorian date-to-Julian day and Julian date-to-Julian day conversion algorithms used to convert Gregorian and Julian dates to the internal representation of seconds. See [9] for a description of the Gregorian date-to-Julian day algorithm and [12] for a description of the Julian date-to-Julian day algorithm. The Custom calendar will have user-defined values for yy, yy_i8, mm, and dd.
The Julian day specifier, d or d_i8, can only be used with the Julian Day and Modified Julian Day calendars, and has a valid range depending on the word size. For a signed 32-bit d, the range for Julian day is [+/- 24855]. For a signed 64-bit d_i8, the valid range for Julian day is [+/- 106,751,991,167,300]. The Julian day number system adheres to the conventional standard where the reference day of d=0 corresponds to 11/24/-4713 in the proleptic Gregorian calendar and 1/1/-4712 in the proleptic Julian calendar. See [17] and [1].
The Modified Julian Day system, introduced by space scientists in the late 1950's, is defined as Julian Day - 2400000.5. See [24].
Note that d and d_i8 are not valid for the No-Calendar. To remain consistent with non-Earth calendars added to ESMF in the future, ESMF requires a calendar to be planet-specific. Hence the No-Calendar does not know what a day is; it cannot assume an Earth day of 86400 seconds.
Hours, minutes, seconds, and sub-seconds can be used with any calendar, since they are standardized units that are the same for any planet.
Time manager represents and manipulates time internally with integers to maintain precision. Hence, user-specified floating point values are converted internally to integers. Sub-second values are represented internally with an integer numerator and denominator fraction (sN/sD). The smallest required resolution is nanoseconds (denominator). For example, pi can be represented as s=3, sN=141592654, sD=1000000000. However, via sN_i8 and sD_i8, larger values can be used. If specifying a constant floating point value, be sure to provide at least 16 digits to take full advantage of double precision, for example s_r8=2.718281828459045d0 for 'e' seconds.
The arguments are:
INTERFACE:
subroutine ESMF_TimeSyncToRealTime(time, rc)ARGUMENTS:
type(ESMF_Time), intent(inout) :: time -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Gets the system real time (wall clock time), and returns it as an ESMF_Time. Accurate to the nearest second.
The arguments are:
INTERFACE:
subroutine ESMF_TimeValidate(time, options, rc)ARGUMENTS:
type(ESMF_Time), intent(in) :: time character (len=*), intent(in), optional :: options integer, intent(out), optional :: rcDESCRIPTION:
Checks whether an ESMF_Time is valid. Must be a valid date/time on a valid calendar. The options control the type of validation.
The arguments are:
There are TimeInterval methods defined for setting and getting a TimeInterval, for incrementing and decrementing a TimeInterval by another TimeInterval, and for multiplying and dividing TimeIntervals by integers, reals, fractions and other TimeIntervals. Methods are also defined to take the absolute value and negative absolute value of a TimeInterval, and for comparing the length of two TimeIntervals.
The class used to represent time instants in ESMF is Time, and this class is frequently used in operations along with TimeIntervals. For example, the difference between two Times is a TimeInterval.
When a TimeInterval is used in calculations that involve an absolute reference time, such as incrementing a Time with a TimeInterval, calendar dependencies may be introduced. The length of the time period that the TimeInterval represents will depend on the reference Time and the standard calendar that is associated with it. The calendar dependency becomes apparent when, for example, adding a TimeInterval of 1 day to the Time of February 28, 1996, at 4:00pm EST. In a 360 day calendar, the resulting date would be February 29, 1996, at 4:00pm EST. In a no-leap calendar, the result would be March 1, 1996, at 4:00pm EST.
TimeIntervals are used by other parts of the ESMF timekeeping system, such as Clocks (Section 41.1) and Alarms (Section 42.1).
A typical use for a TimeInterval in a geophysical model is representation of the time step by which the model is advanced. Some models change the size of their time step as the model run progresses; this could be done by incrementing or decrementing the original time step by another TimeInterval, or by dividing or multiplying the time step by an integer value. An example of advancing model time using a TimeInterval representation of a time step is shown in Section 41.1.
The following brief example shows how to create, initialize and manipulate TimeInterval.
! !PROGRAM: ESMF_TimeIntervalEx - Time Interval initialization and ! manipulation examples ! ! !DESCRIPTION: ! ! This program shows examples of Time Interval initialization and manipulation !----------------------------------------------------------------------------- #include "ESMF.h" ! ESMF Framework module use ESMF use ESMF_TestMod implicit none ! instantiate some time intervals type(ESMF_TimeInterval) :: timeinterval1, timeinterval2, timeinterval3 ! local variables integer :: d, h, m, s ! return code integer:: rc
! initialize ESMF framework call ESMF_Initialize(defaultCalKind=ESMF_CALKIND_GREGORIAN, & defaultlogfilename="TimeIntervalEx.Log", & logkindflag=ESMF_LOGKIND_MULTI, rc=rc)
This example shows how to initialize two ESMF_TimeIntervals.
! initialize time interval1 to 1 day call ESMF_TimeIntervalSet(timeinterval1, d=1, rc=rc)
call ESMF_TimeIntervalPrint(timeinterval1, options="string", rc=rc)
! initialize time interval2 to 4 days, 1 hour, 30 minutes, 10 seconds call ESMF_TimeIntervalSet(timeinterval2, d=4, h=1, m=30, s=10, rc=rc)
call ESMF_TimeIntervalPrint(timeinterval2, options="string", rc=rc)
This example shows how to convert ESMF_TimeIntervals into different units.
call ESMF_TimeIntervalGet(timeinterval1, s=s, rc=rc) print *, "Time Interval1 = ", s, " seconds."
call ESMF_TimeIntervalGet(timeinterval2, h=h, m=m, s=s, rc=rc) print *, "Time Interval2 = ", h, " hours, ", m, " minutes, ", & s, " seconds."
This example shows how to calculate the difference between two ESMF_TimeIntervals.
! difference between two time intervals timeinterval3 = timeinterval2 - timeinterval1 call ESMF_TimeIntervalGet(timeinterval3, d=d, h=h, m=m, s=s, rc=rc) print *, "Difference between TimeInterval2 and TimeInterval1 = ", & d, " days, ", h, " hours, ", m, " minutes, ", s, " seconds."
This example shows how to multiply an ESMF_TimeInterval.
! multiply time interval by an integer timeinterval3 = timeinterval2 * 3 call ESMF_TimeIntervalGet(timeinterval3, d=d, h=h, m=m, s=s, rc=rc) print *, "TimeInterval2 multiplied by 3 = ", d, " days, ", h, & " hours, ", m, " minutes, ", s, " seconds."
This example shows how to compare two ESMF_TimeIntervals.
! comparison if (timeinterval1 < timeinterval2) then print *, "TimeInterval1 is smaller than TimeInterval2" else print *, "TimeInterval1 is larger than or equal to TimeInterval2" end if
end program ESMF_TimeIntervalEx
For fractional seconds, a signed 64-bit integer will handle a resolution of +/- -1, or +/- 9,223,372,036,854,775,807 parts of a second.
INTERFACE:
interface assignment(=) timeinterval1 = timeinterval2ARGUMENTS:
type(ESMF_TimeInterval) :: timeinterval1 type(ESMF_TimeInterval) :: timeinterval2STATUS:
DESCRIPTION:
Set timeinterval1 equal to timeinterval2. This is the default Fortran assignment, which creates a complete, independent copy of timeinterval2 as timeinterval1. If timeinterval2 is an invalid ESMF_TimeInterval object then timeinterval1 will be equally invalid after the assignment.
The arguments are:
INTERFACE:
interface operator(+) sum = timeinterval1 + timeinterval2RETURN VALUE:
type(ESMF_TimeInterval) :: sumARGUMENTS:
type(ESMF_TimeInterval), intent(in) :: timeinterval1 type(ESMF_TimeInterval), intent(in) :: timeinterval2STATUS:
DESCRIPTION:
Overloads the (+) operator for the ESMF_TimeInterval class to add timeinterval1 to timeinterval2 and return the sum as an ESMF_TimeInterval.
The arguments are:
INTERFACE:
interface operator(-) difference = timeinterval1 - timeinterval2RETURN VALUE:
type(ESMF_TimeInterval) :: differenceARGUMENTS:
type(ESMF_TimeInterval), intent(in) :: timeinterval1 type(ESMF_TimeInterval), intent(in) :: timeinterval2STATUS:
DESCRIPTION:
Overloads the (-) operator for the ESMF_TimeInterval class to subtract timeinterval2 from timeinterval1 and return the difference as an ESMF_TimeInterval.
The arguments are:
INTERFACE:
interface operator(-) timeinterval = -timeintervalRETURN VALUE:
type(ESMF_TimeInterval) :: -timeIntervalARGUMENTS:
type(ESMF_TimeInterval), intent(in) :: timeintervalSTATUS:
DESCRIPTION:
Overloads the (-) operator for the ESMF_TimeInterval class to perform unary negation on timeinterval and return the result.
The arguments are:
INTERFACE:
interface operator(/) quotient = timeinterval1 / timeinterval2RETURN VALUE:
real(ESMF_KIND_R8) :: quotientARGUMENTS:
type(ESMF_TimeInterval), intent(in) :: timeinterval1 type(ESMF_TimeInterval), intent(in) :: timeinterval2STATUS:
DESCRIPTION:
Overloads the (/) operator for the ESMF_TimeInterval class to return timeinterval1 divided by timeinterval2 as a double precision quotient.
The arguments are:
INTERFACE:
interface operator(/) quotient = timeinterval / divisorRETURN VALUE:
type(ESMF_TimeInterval) :: quotientARGUMENTS:
type(ESMF_TimeInterval), intent(in) :: timeinterval integer(ESMF_KIND_I4), intent(in) :: divisorSTATUS:
DESCRIPTION:
Overloads the (/) operator for the ESMF_TimeInterval class to divide a timeinterval by an integer divisor, and return the quotient as an ESMF_TimeInterval.
The arguments are:
INTERFACE:
interface MOD function MOD(timeinterval1, timeinterval2)RETURN VALUE:
type(ESMF_TimeInterval) :: MODARGUMENTS:
type(ESMF_TimeInterval), intent(in) :: timeinterval1 type(ESMF_TimeInterval), intent(in) :: timeinterval2STATUS:
DESCRIPTION:
Overloads the Fortran intrinsic MOD() function for the ESMF_TimeInterval class to return the remainder of timeinterval1 divided by timeinterval2 as an ESMF_TimeInterval.
The arguments are:
INTERFACE:
interface operator(*) product = timeinterval * multiplier OR product = multiplier * timeintervalRETURN VALUE:
type(ESMF_TimeInterval) :: productARGUMENTS:
type(ESMF_TimeInterval), intent(in) :: timeinterval integer(ESMF_KIND_I4), intent(in) :: multiplierSTATUS:
DESCRIPTION:
Overloads the (*) operator for the ESMF_TimeInterval class to multiply a timeinterval by an integer multiplier, and return the product as an ESMF_TimeInterval.
The arguments are:
INTERFACE:
interface operator(==) if (timeinterval1 == timeinterval2) then ... endif OR result = (timeinterval1 == timeinterval2)RETURN VALUE:
logical :: resultARGUMENTS:
type(ESMF_TimeInterval), intent(in) :: timeinterval1 type(ESMF_TimeInterval), intent(in) :: timeinterval2STATUS:
DESCRIPTION:
Overloads the (==) operator for the ESMF_TimeInterval class to return .true. if timeinterval1 and timeinterval2 represent an equal duration of time, and .false. otherwise.
The arguments are:
INTERFACE:
interface operator(/=) if (timeinterval1 /= timeinterval2) then ... endif OR result = (timeinterval1 /= timeinterval2)RETURN VALUE:
logical :: resultARGUMENTS:
type(ESMF_TimeInterval), intent(in) :: timeinterval1 type(ESMF_TimeInterval), intent(in) :: timeinterval2STATUS:
DESCRIPTION:
Overloads the (/=) operator for the ESMF_TimeInterval class to return .true. if timeinterval1 and timeinterval2 do not represent an equal duration of time, and .false. otherwise.
The arguments are:
INTERFACE:
interface operator(<) if (timeinterval1 < timeinterval2) then ... endif OR result = (timeinterval1 < timeinterval2)RETURN VALUE:
logical :: resultARGUMENTS:
type(ESMF_TimeInterval), intent(in) :: timeinterval1 type(ESMF_TimeInterval), intent(in) :: timeinterval2STATUS:
DESCRIPTION:
Overloads the (<) operator for the ESMF_TimeInterval class to return .true. if timeinterval1 is a lesser duration of time than timeinterval2, and .false. otherwise.
The arguments are:
INTERFACE:
interface operator(<=) if (timeinterval1 <= timeinterval2) then ... endif OR result = (timeinterval1 <= timeinterval2)RETURN VALUE:
logical :: resultARGUMENTS:
type(ESMF_TimeInterval), intent(in) :: timeinterval1 type(ESMF_TimeInterval), intent(in) :: timeinterval2STATUS:
DESCRIPTION:
Overloads the (<=) operator for the ESMF_TimeInterval class to return .true. if timeinterval1 is a lesser or equal duration of time than timeinterval2, and .false. otherwise.
The arguments are:
INTERFACE:
interface operator(>) if (timeinterval1 > timeinterval2) then ... endif OR result = (timeinterval1 > timeinterval2)RETURN VALUE:
logical :: resultARGUMENTS:
type(ESMF_TimeInterval), intent(in) :: timeinterval1 type(ESMF_TimeInterval), intent(in) :: timeinterval2STATUS:
DESCRIPTION:
Overloads the (>) operator for the ESMF_TimeInterval class to return .true. if timeinterval1 is a greater duration of time than timeinterval2, and .false. otherwise.
The arguments are:
INTERFACE:
interface operator(>=) if (timeinterval1 >= timeinterval2) then ... endif OR result = (timeinterval1 >= timeinterval2)RETURN VALUE:
logical :: resultARGUMENTS:
type(ESMF_TimeInterval), intent(in) :: timeinterval1 type(ESMF_TimeInterval), intent(in) :: timeinterval2STATUS:
DESCRIPTION:
Overloads the (>=) operator for the ESMF_TimeInterval class to return .true. if timeinterval1 is a greater or equal duration of time than timeinterval2, and .false. otherwise.
The arguments are:
INTERFACE:
function ESMF_TimeIntervalAbsValue(timeinterval)RETURN VALUE:
type(ESMF_TimeInterval) :: ESMF_TimeIntervalAbsValueARGUMENTS:
type(ESMF_TimeInterval), intent(in) :: timeintervalSTATUS:
DESCRIPTION:
Returns the absolute value of timeinterval.
The argument is:
INTERFACE:
! Private name; call using ESMF_TimeIntervalGet() subroutine ESMF_TimeIntervalGetDur(timeinterval, & yy, yy_i8, & mm, mm_i8, & d, d_i8, & h, m, & s, s_i8, & ms, us, ns, & d_r8, h_r8, m_r8, s_r8, & ms_r8, us_r8, ns_r8, & sN, sN_i8, sD, sD_i8, & startTime, calendar, calkindflag, & timeString, timeStringISOFrac, rc)ARGUMENTS:
type(ESMF_TimeInterval), intent(in) :: timeinterval -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer(ESMF_KIND_I4), intent(out), optional :: yy integer(ESMF_KIND_I8), intent(out), optional :: yy_i8 integer(ESMF_KIND_I4), intent(out), optional :: mm integer(ESMF_KIND_I8), intent(out), optional :: mm_i8 integer(ESMF_KIND_I4), intent(out), optional :: d integer(ESMF_KIND_I8), intent(out), optional :: d_i8 integer(ESMF_KIND_I4), intent(out), optional :: h integer(ESMF_KIND_I4), intent(out), optional :: m integer(ESMF_KIND_I4), intent(out), optional :: s integer(ESMF_KIND_I8), intent(out), optional :: s_i8 integer(ESMF_KIND_I4), intent(out), optional :: ms integer(ESMF_KIND_I4), intent(out), optional :: us integer(ESMF_KIND_I4), intent(out), optional :: ns real(ESMF_KIND_R8), intent(out), optional :: d_r8 real(ESMF_KIND_R8), intent(out), optional :: h_r8 real(ESMF_KIND_R8), intent(out), optional :: m_r8 real(ESMF_KIND_R8), intent(out), optional :: s_r8 real(ESMF_KIND_R8), intent(out), optional :: ms_r8 real(ESMF_KIND_R8), intent(out), optional :: us_r8 real(ESMF_KIND_R8), intent(out), optional :: ns_r8 integer(ESMF_KIND_I4), intent(out), optional :: sN integer(ESMF_KIND_I8), intent(out), optional :: sN_i8 integer(ESMF_KIND_I4), intent(out), optional :: sD integer(ESMF_KIND_I8), intent(out), optional :: sD_i8 type(ESMF_Time), intent(out), optional :: startTime type(ESMF_Calendar), intent(out), optional :: calendar type(ESMF_CalKind_Flag), intent(out), optional :: calkindflag character (len=*), intent(out), optional :: timeString character (len=*), intent(out), optional :: timeStringISOFrac integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Gets the value of timeinterval in units specified by the user via Fortran optional arguments.
The ESMF Time Manager represents and manipulates time internally with integers to maintain precision. Hence, user-specified floating point values are converted internally from integers.
Units are bound (normalized) to the next larger unit specified. For example, if a time interval is defined to be one day, then ESMF_TimeIntervalGet(d = days, s = seconds) would return days = 1, seconds = 0, whereas ESMF_TimeIntervalGet(s = seconds) would return seconds = 86400.
For timeString, converts ESMF_TimeInterval's value into partial ISO 8601 format PyYmMdDThHmMs[:n/d]S. See [13] and [2]. See also method ESMF_TimeIntervalPrint().
For timeStringISOFrac, converts ESMF_TimeInterval's value into full ISO 8601 format PyYmMdDThHmMs[.f]S. See [13] and [2]. See also method ESMF_TimeIntervalPrint().
The arguments are:
INTERFACE:
! Private name; call using ESMF_TimeIntervalGet() subroutine ESMF_TimeIntervalGetDurStart(timeinterval, startTimeIn, & & yy, yy_i8, & mm, mm_i8, & d, d_i8, & h, m, & s, s_i8, & ms, us, ns, & d_r8, h_r8, m_r8, s_r8, & ms_r8, us_r8, ns_r8, & sN, sN_i8, sD, sD_i8, & startTime, & calendar, calkindflag, & timeString, timeStringISOFrac, rc)ARGUMENTS:
type(ESMF_TimeInterval), intent(in) :: timeinterval type(ESMF_Time), intent(in) :: startTimeIn ! Input -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer(ESMF_KIND_I4), intent(out), optional :: yy integer(ESMF_KIND_I8), intent(out), optional :: yy_i8 integer(ESMF_KIND_I4), intent(out), optional :: mm integer(ESMF_KIND_I8), intent(out), optional :: mm_i8 integer(ESMF_KIND_I4), intent(out), optional :: d integer(ESMF_KIND_I8), intent(out), optional :: d_i8 integer(ESMF_KIND_I4), intent(out), optional :: h integer(ESMF_KIND_I4), intent(out), optional :: m integer(ESMF_KIND_I4), intent(out), optional :: s integer(ESMF_KIND_I8), intent(out), optional :: s_i8 integer(ESMF_KIND_I4), intent(out), optional :: ms integer(ESMF_KIND_I4), intent(out), optional :: us integer(ESMF_KIND_I4), intent(out), optional :: ns real(ESMF_KIND_R8), intent(out), optional :: d_r8 real(ESMF_KIND_R8), intent(out), optional :: h_r8 real(ESMF_KIND_R8), intent(out), optional :: m_r8 real(ESMF_KIND_R8), intent(out), optional :: s_r8 real(ESMF_KIND_R8), intent(out), optional :: ms_r8 real(ESMF_KIND_R8), intent(out), optional :: us_r8 real(ESMF_KIND_R8), intent(out), optional :: ns_r8 integer(ESMF_KIND_I4), intent(out), optional :: sN integer(ESMF_KIND_I8), intent(out), optional :: sN_i8 integer(ESMF_KIND_I4), intent(out), optional :: sD integer(ESMF_KIND_I8), intent(out), optional :: sD_i8 type(ESMF_Time), intent(out), optional :: startTime type(ESMF_Calendar), intent(out), optional :: calendar type(ESMF_CalKind_Flag), intent(out), optional :: calkindflag character (len=*), intent(out), optional :: timeString character (len=*), intent(out), optional :: timeStringISOFrac integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Gets the value of timeinterval in units specified by the user via Fortran optional arguments.
The ESMF Time Manager represents and manipulates time internally with integers to maintain precision. Hence, user-specified floating point values are converted internally from integers.
Units are bound (normalized) to the next larger unit specified. For example, if a time interval is defined to be one day, then ESMF_TimeIntervalGet(d = days, s = seconds) would return days = 1, seconds = 0, whereas ESMF_TimeIntervalGet(s = seconds) would return seconds = 86400.
For timeString, converts ESMF_TimeInterval's value into partial ISO 8601 format PyYmMdDThHmMs[:n/d]S. See [13] and [2]. See also method ESMF_TimeIntervalPrint().
For timeStringISOFrac, converts ESMF_TimeInterval's value into full ISO 8601 format PyYmMdDThHmMs[.f]S. See [13] and [2]. See also method ESMF_TimeIntervalPrint().
The arguments are:
INTERFACE:
! Private name; call using ESMF_TimeIntervalGet() subroutine ESMF_TimeIntervalGetDurCal(timeinterval, calendarIn, & & yy, yy_i8, & mm, mm_i8, & d, d_i8, & h, m, & s, s_i8, & ms, us, ns, & d_r8, h_r8, m_r8, s_r8, & ms_r8, us_r8, ns_r8, & sN, sN_i8, sD, sD_i8, & startTime, & calendar, calkindflag, & timeString, timeStringISOFrac, rc)ARGUMENTS:
type(ESMF_TimeInterval), intent(in) :: timeinterval type(ESMF_Calendar), intent(in) :: calendarIn ! Input -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer(ESMF_KIND_I4), intent(out), optional :: yy integer(ESMF_KIND_I8), intent(out), optional :: yy_i8 integer(ESMF_KIND_I4), intent(out), optional :: mm integer(ESMF_KIND_I8), intent(out), optional :: mm_i8 integer(ESMF_KIND_I4), intent(out), optional :: d integer(ESMF_KIND_I8), intent(out), optional :: d_i8 integer(ESMF_KIND_I4), intent(out), optional :: h integer(ESMF_KIND_I4), intent(out), optional :: m integer(ESMF_KIND_I4), intent(out), optional :: s integer(ESMF_KIND_I8), intent(out), optional :: s_i8 integer(ESMF_KIND_I4), intent(out), optional :: ms integer(ESMF_KIND_I4), intent(out), optional :: us integer(ESMF_KIND_I4), intent(out), optional :: ns real(ESMF_KIND_R8), intent(out), optional :: d_r8 real(ESMF_KIND_R8), intent(out), optional :: h_r8 real(ESMF_KIND_R8), intent(out), optional :: m_r8 real(ESMF_KIND_R8), intent(out), optional :: s_r8 real(ESMF_KIND_R8), intent(out), optional :: ms_r8 real(ESMF_KIND_R8), intent(out), optional :: us_r8 real(ESMF_KIND_R8), intent(out), optional :: ns_r8 integer(ESMF_KIND_I4), intent(out), optional :: sN integer(ESMF_KIND_I8), intent(out), optional :: sN_i8 integer(ESMF_KIND_I4), intent(out), optional :: sD integer(ESMF_KIND_I8), intent(out), optional :: sD_i8 type(ESMF_Time), intent(out), optional :: startTime type(ESMF_Calendar), intent(out), optional :: calendar type(ESMF_CalKind_Flag), intent(out), optional :: calkindflag character (len=*), intent(out), optional :: timeString character (len=*), intent(out), optional :: timeStringISOFrac integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Gets the value of timeinterval in units specified by the user via Fortran optional arguments.
The ESMF Time Manager represents and manipulates time internally with integers to maintain precision. Hence, user-specified floating point values are converted internally from integers.
Units are bound (normalized) to the next larger unit specified. For example, if a time interval is defined to be one day, then ESMF_TimeIntervalGet(d = days, s = seconds) would return days = 1, seconds = 0, whereas ESMF_TimeIntervalGet(s = seconds) would return seconds = 86400.
For timeString, converts ESMF_TimeInterval's value into partial ISO 8601 format PyYmMdDThHmMs[:n/d]S. See [13] and [2]. See also method ESMF_TimeIntervalPrint().
For timeStringISOFrac, converts ESMF_TimeInterval's value into full ISO 8601 format PyYmMdDThHmMs[.f]S. See [13] and [2]. See also method ESMF_TimeIntervalPrint().
The arguments are:
INTERFACE:
! Private name; call using ESMF_TimeIntervalGet() subroutine ESMF_TimeIntervalGetDurCalTyp(timeinterval, calkindflagIn, & & yy, yy_i8, & mm, mm_i8, & d, d_i8, & h, m, & s, s_i8, & ms, us, ns, & d_r8, h_r8, m_r8, s_r8, & ms_r8, us_r8, ns_r8, & sN, sN_i8, sD, sD_i8, & startTime, & calendar, calkindflag, & timeString, & timeStringISOFrac, rc)ARGUMENTS:
type(ESMF_TimeInterval), intent(in) :: timeinterval type(ESMF_CalKind_Flag), intent(in) :: calkindflagIn ! Input -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer(ESMF_KIND_I4), intent(out), optional :: yy integer(ESMF_KIND_I8), intent(out), optional :: yy_i8 integer(ESMF_KIND_I4), intent(out), optional :: mm integer(ESMF_KIND_I8), intent(out), optional :: mm_i8 integer(ESMF_KIND_I4), intent(out), optional :: d integer(ESMF_KIND_I8), intent(out), optional :: d_i8 integer(ESMF_KIND_I4), intent(out), optional :: h integer(ESMF_KIND_I4), intent(out), optional :: m integer(ESMF_KIND_I4), intent(out), optional :: s integer(ESMF_KIND_I8), intent(out), optional :: s_i8 integer(ESMF_KIND_I4), intent(out), optional :: ms integer(ESMF_KIND_I4), intent(out), optional :: us integer(ESMF_KIND_I4), intent(out), optional :: ns real(ESMF_KIND_R8), intent(out), optional :: d_r8 real(ESMF_KIND_R8), intent(out), optional :: h_r8 real(ESMF_KIND_R8), intent(out), optional :: m_r8 real(ESMF_KIND_R8), intent(out), optional :: s_r8 real(ESMF_KIND_R8), intent(out), optional :: ms_r8 real(ESMF_KIND_R8), intent(out), optional :: us_r8 real(ESMF_KIND_R8), intent(out), optional :: ns_r8 integer(ESMF_KIND_I4), intent(out), optional :: sN integer(ESMF_KIND_I8), intent(out), optional :: sN_i8 integer(ESMF_KIND_I4), intent(out), optional :: sD integer(ESMF_KIND_I8), intent(out), optional :: sD_i8 type(ESMF_Time), intent(out), optional :: startTime type(ESMF_Calendar), intent(out), optional :: calendar type(ESMF_CalKind_Flag), intent(out), optional :: calkindflag character (len=*), intent(out), optional :: timeString character (len=*), intent(out), optional :: timeStringISOFrac integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Gets the value of timeinterval in units specified by the user via Fortran optional arguments.
The ESMF Time Manager represents and manipulates time internally with integers to maintain precision. Hence, user-specified floating point values are converted internally from integers.
Units are bound (normalized) to the next larger unit specified. For example, if a time interval is defined to be one day, then ESMF_TimeIntervalGet(d = days, s = seconds) would return days = 1, seconds = 0, whereas ESMF_TimeIntervalGet(s = seconds) would return seconds = 86400.
For timeString, converts ESMF_TimeInterval's value into partial ISO 8601 format PyYmMdDThHmMs[:n/d]S. See [13] and [2]. See also method ESMF_TimeIntervalPrint().
For timeStringISOFrac, converts ESMF_TimeInterval's value into full ISO 8601 format PyYmMdDThHmMs[.f]S. See [13] and [2]. See also method ESMF_TimeIntervalPrint().
The arguments are:
INTERFACE:
function ESMF_TimeIntervalNegAbsValue(timeinterval)RETURN VALUE:
type(ESMF_TimeInterval) :: ESMF_TimeIntervalNegAbsValueARGUMENTS:
type(ESMF_TimeInterval), intent(in) :: timeintervalSTATUS:
DESCRIPTION:
Returns the negative absolute value of timeinterval.
The argument is:
INTERFACE:
subroutine ESMF_TimeIntervalPrint(timeinterval, options, rc)ARGUMENTS:
type(ESMF_TimeInterval), intent(in) :: timeinterval character (len=*), intent(in), optional :: options integer, intent(out), optional :: rcDESCRIPTION:
Prints out the contents of an ESMF_TimeInterval to stdout,
in support of testing and debugging. The options control the type of
information and level of detail.
The arguments are:
INTERFACE:
! Private name; call using ESMF_TimeIntervalSet() subroutine ESMF_TimeIntervalSetDur(timeinterval, & yy, yy_i8, & mm, mm_i8, & d, d_i8, & h, m, & s, s_i8, & ms, us, ns, & d_r8, h_r8, m_r8, s_r8, & ms_r8, us_r8, ns_r8, & sN, sN_i8, sD, sD_i8, rc)ARGUMENTS:
type(ESMF_TimeInterval), intent(inout) :: timeinterval -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer(ESMF_KIND_I4), intent(in), optional :: yy integer(ESMF_KIND_I8), intent(in), optional :: yy_i8 integer(ESMF_KIND_I4), intent(in), optional :: mm integer(ESMF_KIND_I8), intent(in), optional :: mm_i8 integer(ESMF_KIND_I4), intent(in), optional :: d integer(ESMF_KIND_I8), intent(in), optional :: d_i8 integer(ESMF_KIND_I4), intent(in), optional :: h integer(ESMF_KIND_I4), intent(in), optional :: m integer(ESMF_KIND_I4), intent(in), optional :: s integer(ESMF_KIND_I8), intent(in), optional :: s_i8 integer(ESMF_KIND_I4), intent(in), optional :: ms integer(ESMF_KIND_I4), intent(in), optional :: us integer(ESMF_KIND_I4), intent(in), optional :: ns real(ESMF_KIND_R8), intent(in), optional :: d_r8 real(ESMF_KIND_R8), intent(in), optional :: h_r8 real(ESMF_KIND_R8), intent(in), optional :: m_r8 real(ESMF_KIND_R8), intent(in), optional :: s_r8 real(ESMF_KIND_R8), intent(in), optional :: ms_r8 real(ESMF_KIND_R8), intent(in), optional :: us_r8 real(ESMF_KIND_R8), intent(in), optional :: ns_r8 integer(ESMF_KIND_I4), intent(in), optional :: sN integer(ESMF_KIND_I8), intent(in), optional :: sN_i8 integer(ESMF_KIND_I4), intent(in), optional :: sD integer(ESMF_KIND_I8), intent(in), optional :: sD_i8 integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Sets the value of the ESMF_TimeInterval in units specified by the user via Fortran optional arguments.
The ESMF Time Manager represents and manipulates time internally with integers to maintain precision. Hence, user-specified floating point values are converted internally to integers.
Ranges are limited only by machine word size. Numeric defaults are 0, except for sD, which is 1.
The arguments are:
INTERFACE:
! Private name; call using ESMF_TimeIntervalSet() subroutine ESMF_TimeIntervalSetDurStart(timeinterval, startTime, & & yy, yy_i8, & mm, mm_i8, & d, d_i8, & h, m, & s, s_i8, & ms, us, ns, & d_r8, h_r8, m_r8, s_r8, & ms_r8, us_r8, ns_r8, & sN, sN_i8, sD, sD_i8, & rc)ARGUMENTS:
type(ESMF_TimeInterval), intent(inout) :: timeinterval type(ESMF_Time), intent(in) :: startTime -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer(ESMF_KIND_I4), intent(in), optional :: yy integer(ESMF_KIND_I8), intent(in), optional :: yy_i8 integer(ESMF_KIND_I4), intent(in), optional :: mm integer(ESMF_KIND_I8), intent(in), optional :: mm_i8 integer(ESMF_KIND_I4), intent(in), optional :: d integer(ESMF_KIND_I8), intent(in), optional :: d_i8 integer(ESMF_KIND_I4), intent(in), optional :: h integer(ESMF_KIND_I4), intent(in), optional :: m integer(ESMF_KIND_I4), intent(in), optional :: s integer(ESMF_KIND_I8), intent(in), optional :: s_i8 integer(ESMF_KIND_I4), intent(in), optional :: ms integer(ESMF_KIND_I4), intent(in), optional :: us integer(ESMF_KIND_I4), intent(in), optional :: ns real(ESMF_KIND_R8), intent(in), optional :: d_r8 real(ESMF_KIND_R8), intent(in), optional :: h_r8 real(ESMF_KIND_R8), intent(in), optional :: m_r8 real(ESMF_KIND_R8), intent(in), optional :: s_r8 real(ESMF_KIND_R8), intent(in), optional :: ms_r8 real(ESMF_KIND_R8), intent(in), optional :: us_r8 real(ESMF_KIND_R8), intent(in), optional :: ns_r8 integer(ESMF_KIND_I4), intent(in), optional :: sN integer(ESMF_KIND_I8), intent(in), optional :: sN_i8 integer(ESMF_KIND_I4), intent(in), optional :: sD integer(ESMF_KIND_I8), intent(in), optional :: sD_i8 integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Sets the value of the ESMF_TimeInterval in units specified by the user via Fortran optional arguments.
The ESMF Time Manager represents and manipulates time internally with integers to maintain precision. Hence, user-specified floating point values are converted internally to integers.
Ranges are limited only by machine word size. Numeric defaults are 0, except for sD, which is 1.
The arguments are:
INTERFACE:
! Private name; call using ESMF_TimeIntervalSet() subroutine ESMF_TimeIntervalSetDurCal(timeinterval, calendar, & & yy, yy_i8, & mm, mm_i8, & d, d_i8, & h, m, & s, s_i8, & ms, us, ns, & d_r8, h_r8, m_r8, s_r8, & ms_r8, us_r8, ns_r8, & sN, sN_i8, sD, sD_i8, rc)ARGUMENTS:
type(ESMF_TimeInterval), intent(inout) :: timeinterval type(ESMF_Calendar), intent(in) :: calendar -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer(ESMF_KIND_I4), intent(in), optional :: yy integer(ESMF_KIND_I8), intent(in), optional :: yy_i8 integer(ESMF_KIND_I4), intent(in), optional :: mm integer(ESMF_KIND_I8), intent(in), optional :: mm_i8 integer(ESMF_KIND_I4), intent(in), optional :: d integer(ESMF_KIND_I8), intent(in), optional :: d_i8 integer(ESMF_KIND_I4), intent(in), optional :: h integer(ESMF_KIND_I4), intent(in), optional :: m integer(ESMF_KIND_I4), intent(in), optional :: s integer(ESMF_KIND_I8), intent(in), optional :: s_i8 integer(ESMF_KIND_I4), intent(in), optional :: ms integer(ESMF_KIND_I4), intent(in), optional :: us integer(ESMF_KIND_I4), intent(in), optional :: ns real(ESMF_KIND_R8), intent(in), optional :: d_r8 real(ESMF_KIND_R8), intent(in), optional :: h_r8 real(ESMF_KIND_R8), intent(in), optional :: m_r8 real(ESMF_KIND_R8), intent(in), optional :: s_r8 real(ESMF_KIND_R8), intent(in), optional :: ms_r8 real(ESMF_KIND_R8), intent(in), optional :: us_r8 real(ESMF_KIND_R8), intent(in), optional :: ns_r8 integer(ESMF_KIND_I4), intent(in), optional :: sN integer(ESMF_KIND_I8), intent(in), optional :: sN_i8 integer(ESMF_KIND_I4), intent(in), optional :: sD integer(ESMF_KIND_I8), intent(in), optional :: sD_i8 integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Sets the value of the ESMF_TimeInterval in units specified by the user via Fortran optional arguments.
The ESMF Time Manager represents and manipulates time internally with integers to maintain precision. Hence, user-specified floating point values are converted internally to integers.
Ranges are limited only by machine word size. Numeric defaults are 0, except for sD, which is 1.
The arguments are:
INTERFACE:
! Private name; call using ESMF_TimeIntervalSet() subroutine ESMF_TimeIntervalSetDurCalTyp(timeinterval, calkindflag, & & yy, yy_i8, & mm, mm_i8, & d, d_i8, & h, m, & s, s_i8, & ms, us, ns, & d_r8, h_r8, m_r8, s_r8, & ms_r8, us_r8, ns_r8, & sN, sN_i8, sD, sD_i8, & rc)ARGUMENTS:
type(ESMF_TimeInterval), intent(inout) :: timeinterval type(ESMF_CalKind_Flag), intent(in) :: calkindflag -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer(ESMF_KIND_I4), intent(in), optional :: yy integer(ESMF_KIND_I8), intent(in), optional :: yy_i8 integer(ESMF_KIND_I4), intent(in), optional :: mm integer(ESMF_KIND_I8), intent(in), optional :: mm_i8 integer(ESMF_KIND_I4), intent(in), optional :: d integer(ESMF_KIND_I8), intent(in), optional :: d_i8 integer(ESMF_KIND_I4), intent(in), optional :: h integer(ESMF_KIND_I4), intent(in), optional :: m integer(ESMF_KIND_I4), intent(in), optional :: s integer(ESMF_KIND_I8), intent(in), optional :: s_i8 integer(ESMF_KIND_I4), intent(in), optional :: ms integer(ESMF_KIND_I4), intent(in), optional :: us integer(ESMF_KIND_I4), intent(in), optional :: ns real(ESMF_KIND_R8), intent(in), optional :: d_r8 real(ESMF_KIND_R8), intent(in), optional :: h_r8 real(ESMF_KIND_R8), intent(in), optional :: m_r8 real(ESMF_KIND_R8), intent(in), optional :: s_r8 real(ESMF_KIND_R8), intent(in), optional :: ms_r8 real(ESMF_KIND_R8), intent(in), optional :: us_r8 real(ESMF_KIND_R8), intent(in), optional :: ns_r8 integer(ESMF_KIND_I4), intent(in), optional :: sN integer(ESMF_KIND_I8), intent(in), optional :: sN_i8 integer(ESMF_KIND_I4), intent(in), optional :: sD integer(ESMF_KIND_I8), intent(in), optional :: sD_i8 integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Sets the value of the ESMF_TimeInterval in units specified by the user via Fortran optional arguments.
The ESMF Time Manager represents and manipulates time internally with integers to maintain precision. Hence, user-specified floating point values are converted internally to integers.
Ranges are limited only by machine word size. Numeric defaults are 0, except for sD, which is 1.
The arguments are:
INTERFACE:
subroutine ESMF_TimeIntervalValidate(timeinterval, rc)ARGUMENTS:
type(ESMF_TimeInterval), intent(in) :: timeinterval -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Checks whether a timeinterval is valid. If fractional value, denominator must be non-zero.
The arguments are:
The Clock class advances model time and tracks its associated date on a specified Calendar. It stores start time, stop time, current time, previous time, and a time step. It can also store a reference time, typically the time instant at which a simulation originally began. For a restart run, the reference time can be different than the start time, when the application execution resumes.
A user can call the ESMF_ClockSet method and reset the time step as desired.
A Clock also stores a list of Alarms, which can be set to flag events that occur at a specified time instant or at a specified time interval. See Section 42.1 for details on how to use Alarms.
There are methods for setting and getting the Times and Alarms associated with a Clock. Methods are defined for advancing the Clock's current time, checking if the stop time has been reached, reversing direction, and synchronizing with a real clock.
DESCRIPTION:
Specifies the time-stepping direction of a clock. Use with "direction"
argument to methods ESMF_ClockSet() and ESMF_ClockGet().
Cannot be used with method ESMF_ClockCreate(), since it only
initializes a clock in the default forward mode; a clock must be advanced
(timestepped) at least once before reversing direction via
ESMF_ClockSet(). This also holds true for negative timestep clocks
which are initialized (created) with stopTime < startTime, since "forward"
means timestepping from startTime towards stopTime
(see ESMF_DIRECTION_FORWARD below).
"Forward" and "reverse" directions are distinct from postive and negative timesteps. "Forward" means timestepping in the direction established at ESMF_ClockCreate(), from startTime towards stopTime, regardless of the timestep sign. "Reverse" means timestepping in the opposite direction, back towards the clock's startTime, regardless of the timestep sign.
Clocks and alarms run in reverse in such a way that the state of a clock and its alarms after each time step is precisely replicated as it was in forward time-stepping mode. All methods which query clock and alarm state will return the same result for a given timeStep, regardless of the direction of arrival.
The type of this flag is:
type(ESMF_Direction_Flag)
The valid values are:
The following is a typical sequence for using a Clock in a geophysical model.
At initialize:
At run:
At finalize:
The following code example illustrates Clock usage.
! !PROGRAM: ESMF_ClockEx - Clock initialization and time-stepping ! ! !DESCRIPTION: ! ! This program shows an example of how to create, initialize, advance, and ! examine a basic clock !----------------------------------------------------------------------------- #include "ESMF.h" ! ESMF Framework module use ESMF use ESMF_TestMod implicit none ! instantiate a clock type(ESMF_Clock) :: clock ! instantiate time_step, start and stop times type(ESMF_TimeInterval) :: timeStep type(ESMF_Time) :: startTime type(ESMF_Time) :: stopTime ! local variables for Get methods type(ESMF_Time) :: currTime integer(ESMF_KIND_I8) :: advanceCount integer :: YY, MM, DD, H, M, S ! return code integer :: rc
! initialize ESMF framework call ESMF_Initialize(defaultCalKind=ESMF_CALKIND_GREGORIAN, & defaultlogfilename="ClockEx.Log", & logkindflag=ESMF_LOGKIND_MULTI, rc=rc)
This example shows how to create and initialize an ESMF_Clock.
! initialize time interval to 2 days, 4 hours (6 timesteps in 13 days) call ESMF_TimeIntervalSet(timeStep, d=2, h=4, rc=rc)
! initialize start time to 4/1/2003 2:24:00 ( 1/10 of a day ) call ESMF_TimeSet(startTime, yy=2003, mm=4, dd=1, h=2, m=24, rc=rc)
! initialize stop time to 4/14/2003 2:24:00 ( 1/10 of a day ) call ESMF_TimeSet(stopTime, yy=2003, mm=4, dd=14, h=2, m=24, rc=rc)
! initialize the clock with the above values clock = ESMF_ClockCreate(timeStep, startTime, stopTime=stopTime, & name="Clock 1", rc=rc)
This example shows how to time-step an ESMF_Clock.
! time step clock from start time to stop time do while (.not.ESMF_ClockIsStopTime(clock, rc=rc))
call ESMF_ClockPrint(clock, options="currTime string", rc=rc)
call ESMF_ClockAdvance(clock, rc=rc)
end do
This example shows how to examine an ESMF_Clock.
! get the clock's final current time call ESMF_ClockGet(clock, currTime=currTime, rc=rc)
call ESMF_TimeGet(currTime, yy=YY, mm=MM, dd=DD, h=H, m=M, s=S, rc=rc) print *, "The clock's final current time is ", YY, "/", MM, "/", DD, & " ", H, ":", M, ":", S
! get the number of times the clock was advanced call ESMF_ClockGet(clock, advanceCount=advanceCount, rc=rc) print *, "The clock was advanced ", advanceCount, " times."
This example shows how to time-step an ESMF_Clock in reverse mode.
call ESMF_ClockSet(clock, direction=ESMF_DIRECTION_REVERSE, rc=rc)
! time step clock in reverse from stop time back to start time; ! note use of ESMF_ClockIsDone() rather than ESMF_ClockIsStopTime() do while (.not.ESMF_ClockIsDone(clock, rc=rc))
call ESMF_ClockPrint(clock, options="currTime string", rc=rc)
call ESMF_ClockAdvance(clock, rc=rc)
end do
This example shows how to destroy an ESMF_Clock.
! destroy clock call ESMF_ClockDestroy(clock, rc=rc)
! finalize ESMF framework call ESMF_Finalize(rc=rc)
end program ESMF_ClockEx
INTERFACE:
interface assignment(=) clock1 = clock2ARGUMENTS:
type(ESMF_Clock) :: clock1 type(ESMF_Clock) :: clock2STATUS:
DESCRIPTION:
Assign clock1 as an alias to the same ESMF_Clock object in memory as clock2. If clock2 is invalid, then clock1 will be equally invalid after the assignment.
The arguments are:
INTERFACE:
interface operator(==) if (clock1 == clock2) then ... endif OR result = (clock1 == clock2)RETURN VALUE:
logical :: resultARGUMENTS:
type(ESMF_Clock), intent(in) :: clock1 type(ESMF_Clock), intent(in) :: clock2DESCRIPTION:
Overloads the (==) operator for the ESMF_Clock class. Compare two clocks for equality; return .true. if equal, .false. otherwise. Comparison is based on IDs, which are distinct for newly created clocks and identical for clocks created as copies.
If either side of the equality test is not in the ESMF_INIT_CREATED status an error will be logged. However, this does not affect the return value, which is .true. when both sides are in the same status, and .false. otherwise.
The arguments are:
INTERFACE:
interface operator(/=) if (clock1 /= clock2) then ... endif OR result = (clock1 /= clock2)RETURN VALUE:
logical :: resultARGUMENTS:
type(ESMF_Clock), intent(in) :: clock1 type(ESMF_Clock), intent(in) :: clock2DESCRIPTION:
Overloads the (/=) operator for the ESMF_Clock class. Compare two clocks for inequality; return .true. if not equal, .false. otherwise. Comparison is based on IDs, which are distinct for newly created clocks and identical for clocks created as copies.
If either side of the equality test is not in the ESMF_INIT_CREATED status an error will be logged. However, this does not affect the return value, which is .true. when both sides are not in the same status, and .false. otherwise.
The arguments are:
INTERFACE:
subroutine ESMF_ClockAdvance(clock, & timeStep, ringingAlarmList, ringingAlarmCount, rc)ARGUMENTS:
type(ESMF_Clock), intent(inout) :: clock -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_TimeInterval), intent(in), optional :: timeStep type(ESMF_Alarm), intent(out), optional :: ringingAlarmList(:) integer, intent(out), optional :: ringingAlarmCount integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Advances the clock's current time by one time step: either the clock's, or the passed-in timeStep (see below). When the clock is in ESMF_DIRECTION_FORWARD (default), this method adds the timeStep to the clock's current time. In ESMF_DIRECTION_REVERSE, timeStep is subtracted from the current time. In either case, timeStep can be positive or negative. See the "direction" argument in method ESMF_ClockSet(). ESMF_ClockAdvance() optionally returns a list and number of ringing ESMF_Alarms. See also method ESMF_ClockGetRingingAlarms().
The arguments are:
INTERFACE:
! Private name; call using ESMF_ClockCreate() function ESMF_ClockCreateNew(timeStep, startTime, & stopTime, runDuration, runTimeStepCount, refTime, name, rc)RETURN VALUE:
type(ESMF_Clock) :: ESMF_ClockCreateNewARGUMENTS:
type(ESMF_TimeInterval), intent(in) :: timeStep type(ESMF_Time), intent(in) :: startTime -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_Time), intent(in), optional :: stopTime type(ESMF_TimeInterval), intent(in), optional :: runDuration integer, intent(in), optional :: runTimeStepCount type(ESMF_Time), intent(in), optional :: refTime character (len=*), intent(in), optional :: name integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Creates and sets the initial values in a new ESMF_Clock.
The arguments are:
INTERFACE:
! Private name; call using ESMF_ClockCreate() function ESMF_ClockCreateCopy(clock, rc)RETURN VALUE:
type(ESMF_Clock) :: ESMF_ClockCreateCopyARGUMENTS:
type(ESMF_Clock), intent(in) :: clock -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Creates a deep copy of a given ESMF_Clock, but does not copy its list of ESMF_Alarms (pointers), since an ESMF_Alarm can only be associated with one ESMF_Clock. Hence, the returned ESMF_Clock copy has no associated ESMF_Alarms, the same as with a newly created ESMF_Clock. If desired, new ESMF_Alarms must be created and associated with this copied ESMF_Clock via ESMF_AlarmCreate(), or existing ESMF_Alarms must be re-associated with this copied ESMF_Clock via ESMF_AlarmSet(...clock=...).
The arguments are:
INTERFACE:
subroutine ESMF_ClockDestroy(clock, rc)ARGUMENTS:
type(ESMF_Clock), intent(inout) :: clock -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Releases resources associated with this ESMF_Clock. This releases the list of associated ESMF_Alarms (pointers), but not the ESMF_Alarms themselves; the user must explicitly call ESMF_AlarmDestroy() on each ESMF_Alarm to release its resources. ESMF_ClockDestroy() and corresponding ESMF_AlarmDestroy()s can be called in either order.
If ESMF_ClockDestroy() is called before ESMF_AlarmDestroy(), any ESMF_Alarms that were in the ESMF_Clock's list will no longer be associated with any ESMF_Clock. If desired, these "orphaned" ESMF_Alarms can be associated with a different ESMF_Clock via a call to ESMF_AlarmSet(...clock=...).
The arguments are:
INTERFACE:
subroutine ESMF_ClockGet(clock, & timeStep, startTime, stopTime, & runDuration, runTimeStepCount, refTime, currTime, prevTime, & currSimTime, prevSimTime, calendar, calkindflag, timeZone, & advanceCount, alarmCount, direction, name, rc)ARGUMENTS:
type(ESMF_Clock), intent(in) :: clock -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_TimeInterval), intent(out), optional :: timeStep type(ESMF_Time), intent(out), optional :: startTime type(ESMF_Time), intent(out), optional :: stopTime type(ESMF_TimeInterval), intent(out), optional :: runDuration real(ESMF_KIND_R8), intent(out), optional :: runTimeStepCount type(ESMF_Time), intent(out), optional :: refTime type(ESMF_Time), intent(out), optional :: currTime type(ESMF_Time), intent(out), optional :: prevTime type(ESMF_TimeInterval), intent(out), optional :: currSimTime type(ESMF_TimeInterval), intent(out), optional :: prevSimTime type(ESMF_Calendar), intent(out), optional :: calendar type(ESMF_CalKind_Flag), intent(out), optional :: calkindflag integer, intent(out), optional :: timeZone integer(ESMF_KIND_I8), intent(out), optional :: advanceCount integer, intent(out), optional :: alarmCount type(ESMF_Direction_Flag), intent(out), optional :: direction character (len=*), intent(out), optional :: name integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Gets one or more of the properties of an ESMF_Clock.
The arguments are:
INTERFACE:
subroutine ESMF_ClockGetAlarm(clock, alarmname, alarm, & rc)ARGUMENTS:
type(ESMF_Clock), intent(in) :: clock character (len=*), intent(in) :: alarmname type(ESMF_Alarm), intent(out) :: alarm -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Gets the alarm whose name is the value of alarmname in the clock's ESMF_Alarm list.
The arguments are:
INTERFACE:
subroutine ESMF_ClockGetAlarmList(clock, alarmlistflag, & timeStep, alarmList, alarmCount, rc)ARGUMENTS:
type(ESMF_Clock), intent(in) :: clock type(ESMF_AlarmList_Flag), intent(in) :: alarmlistflag -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_TimeInterval), intent(in), optional :: timeStep type(ESMF_Alarm), intent(out), optional :: alarmList(:) integer, intent(out), optional :: alarmCount integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Gets the clock's list of alarms and/or number of alarms.
The arguments are:
ESMF_ALARMLIST_ALL : Returns the ESMF_Clock's entire list of alarms.
ESMF_ALARMLIST_NEXTRINGING : Return only those alarms that will ring upon the next clock time step. Can optionally specify argument timeStep (see below) to use instead of the clock's. See also method ESMF_AlarmWillRingNext() for checking a single alarm.
ESMF_ALARMLIST_PREVRINGING : Return only those alarms that were ringing on the previous ESMF_Clock time step. See also method ESMF_AlarmWasPrevRinging() for checking a single alarm.
ESMF_ALARMLIST_RINGING : Returns only those clock alarms that are currently ringing. See also method ESMF_ClockAdvance() for getting the list of ringing alarms subsequent to a time step. See also method ESMF_AlarmIsRinging() for checking a single alarm.
INTERFACE:
subroutine ESMF_ClockGetNextTime(clock, nextTime, & timeStep, rc)ARGUMENTS:
type(ESMF_Clock), intent(in) :: clock type(ESMF_Time), intent(out) :: nextTime -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_TimeInterval), intent(in), optional :: timeStep integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Calculates what the next time of the clock will be, based on the clock's current time step or an optionally passed-in timeStep.
The arguments are:
INTERFACE:
function ESMF_ClockIsDone(clock, rc)RETURN VALUE:
logical :: ESMF_ClockIsDoneARGUMENTS:
type(ESMF_Clock), intent(in) :: clock -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Returns true if currentTime is greater than or equal to stopTime in ESMF_DIRECTION_FORWARD, or if currentTime is less than or equal to startTime in ESMF_DIRECTION_REVERSE. It returns false otherwise.
The arguments are:
INTERFACE:
function ESMF_ClockIsReverse(clock, rc)RETURN VALUE:
logical :: ESMF_ClockIsReverseARGUMENTS:
type(ESMF_Clock), intent(in) :: clock -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Returns true if clock is in ESMF_DIRECTION_REVERSE, and false if in ESMF_DIRECTION_FORWARD. Allows convenient use in "if" and "do while" constructs. Alternative to ESMF_ClockGet(...direction=...).
The arguments are:
INTERFACE:
function ESMF_ClockIsStopTime(clock, rc)RETURN VALUE:
logical :: ESMF_ClockIsStopTimeARGUMENTS:
type(ESMF_Clock), intent(in) :: clock -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Returns true if the clock has reached or exceeded its stop time, and false otherwise.
The arguments are:
INTERFACE:
function ESMF_ClockIsStopTimeEnabled(clock, rc)RETURN VALUE:
logical :: ESMF_ClockIsStopTimeEnabledARGUMENTS:
type(ESMF_Clock), intent(in) :: clock -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Returns true if the clock's stop time is set and enabled, and false otherwise.
The arguments are:
INTERFACE:
subroutine ESMF_ClockPrint(clock, options, rc)ARGUMENTS:
type(ESMF_Clock), intent(in) :: clock character (len=*), intent(in), optional :: options integer, intent(out), optional :: rcDESCRIPTION:
Prints out an ESMF_Clock's properties to stdout, in
support of testing and debugging. The options control the type of
information and level of detail.
The arguments are:
INTERFACE:
subroutine ESMF_ClockSet(clock, & timeStep, startTime, stopTime, & runDuration, runTimeStepCount, refTime, currTime, advanceCount, & direction, name, rc)ARGUMENTS:
type(ESMF_Clock), intent(inout) :: clock -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_TimeInterval), intent(in), optional :: timeStep type(ESMF_Time), intent(in), optional :: startTime type(ESMF_Time), intent(in), optional :: stopTime type(ESMF_TimeInterval), intent(in), optional :: runDuration integer, intent(in), optional :: runTimeStepCount type(ESMF_Time), intent(in), optional :: refTime type(ESMF_Time), intent(in), optional :: currTime integer(ESMF_KIND_I8), intent(in), optional :: advanceCount type(ESMF_Direction_Flag), intent(in), optional :: direction character (len=*), intent(in), optional :: name integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Sets/resets one or more of the properties of an ESMF_Clock that was previously initialized via ESMF_ClockCreate().
The arguments are:
INTERFACE:
subroutine ESMF_ClockStopTimeDisable(clock, rc)ARGUMENTS:
type(ESMF_Clock), intent(inout) :: clock -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Disables a ESMF_Clock's stop time; ESMF_ClockIsStopTime() will always return false, allowing a clock to run past its stopTime.
The arguments are:
INTERFACE:
subroutine ESMF_ClockStopTimeEnable(clock, stopTime, rc)ARGUMENTS:
type(ESMF_Clock), intent(inout) :: clock -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_Time), intent(in), optional :: stopTime integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Enables a ESMF_Clock's stop time, allowing ESMF_ClockIsStopTime() to respect the stopTime.
The arguments are:
INTERFACE:
subroutine ESMF_ClockSyncToRealTime(clock, rc)ARGUMENTS:
type(ESMF_Clock), intent(inout) :: clock -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Sets a clock's current time to the wall clock time. It is accurate to the nearest second.
The arguments are:
INTERFACE:
subroutine ESMF_ClockValidate(clock, rc)ARGUMENTS:
type(ESMF_Clock), intent(in) :: clock -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Checks whether a clock is valid. Must have a valid startTime and timeStep. If clock has a stopTime, its currTime must be within startTime to stopTime, inclusive; also startTime's and stopTime's calendars must be the same.
The arguments are:
The Alarm class identifies events that occur at specific Times or specific TimeIntervals by returning a true value at those times or subsequent times, and a false value otherwise.
DESCRIPTION:
Specifies the characteristics of Alarms that populate
a retrieved Alarm list.
The type of this flag is:
type(ESMF_AlarmList_Flag)
The valid values are:
Alarms are used in conjunction with Clocks (see Section 41.1). Multiple Alarms can be associated with a Clock. During the ESMF_ClockAdvance() method, a Clock iterates over its internal Alarms to determine if any are ringing. Alarms ring when a specified Alarm time is reached or exceeded, taking into account whether the time step is positive or negative. In ESMF_DIRECTION_REVERSE (see Section 41.1), alarms ring in reverse, i.e., they begin ringing when they originally ended, and end ringing when they originally began. On completion of the time advance call, the Clock optionally returns a list of ringing alarms.
Each ringing Alarm can then be processed using Alarm methods for identifying, turning off, disabling or resetting the Alarm.
Alarm methods are defined for obtaining the ringing state, turning the ringer on/off, enabling/disabling the Alarm, and getting/setting associated times.
The following example shows how to set and process Alarms.
! !PROGRAM: ESMF_AlarmEx - Alarm examples ! ! !DESCRIPTION: ! ! This program shows an example of how to create, initialize, and process ! alarms associated with a clock. !----------------------------------------------------------------------------- #include "ESMF.h" ! ESMF Framework module use ESMF use ESMF_TestMod implicit none ! instantiate time_step, start, stop, and alarm times type(ESMF_TimeInterval) :: timeStep, alarmInterval type(ESMF_Time) :: alarmTime, startTime, stopTime ! instantiate a clock type(ESMF_Clock) :: clock ! instantiate Alarm lists integer, parameter :: NUMALARMS = 2 type(ESMF_Alarm) :: alarm(NUMALARMS) ! local variables for Get methods integer :: ringingAlarmCount ! at any time step (0 to NUMALARMS) ! name, loop counter, result code character (len=ESMF_MAXSTR) :: name integer :: i, rc, result
! initialize ESMF framework call ESMF_Initialize(defaultCalKind=ESMF_CALKIND_GREGORIAN, & defaultlogfilename="AlarmEx.Log", & logkindflag=ESMF_LOGKIND_MULTI, rc=rc)
This example shows how to create and initialize an ESMF_Clock.
! initialize time interval to 1 day call ESMF_TimeIntervalSet(timeStep, d=1, rc=rc)
! initialize start time to 9/1/2003 call ESMF_TimeSet(startTime, yy=2003, mm=9, dd=1, rc=rc)
! initialize stop time to 9/30/2003 call ESMF_TimeSet(stopTime, yy=2003, mm=9, dd=30, rc=rc)
! create & initialize the clock with the above values clock = ESMF_ClockCreate(timeStep, startTime, stopTime=stopTime, & name="The Clock", rc=rc)
This example shows how to create and initialize two ESMF_Alarms and associate them with the clock.
! Initialize first alarm to be a one-shot on 9/15/2003 and associate ! it with the clock call ESMF_TimeSet(alarmTime, yy=2003, mm=9, dd=15, rc=rc)
alarm(1) = ESMF_AlarmCreate(clock, & ringTime=alarmTime, name="Example alarm 1", rc=rc)
! Initialize second alarm to ring on a 1 week interval starting 9/1/2003 ! and associate it with the clock call ESMF_TimeSet(alarmTime, yy=2003, mm=9, dd=1, rc=rc)
call ESMF_TimeIntervalSet(alarmInterval, d=7, rc=rc)
! Alarm gets default name "Alarm002" alarm(2) = ESMF_AlarmCreate(clock=clock, ringTime=alarmTime, & ringInterval=alarmInterval, rc=rc)
This example shows how to advance an ESMF_Clock and process any resulting ringing alarms.
! time step clock from start time to stop time do while (.not.ESMF_ClockIsStopTime(clock, rc=rc))
! perform time step and get the number of any ringing alarms call ESMF_ClockAdvance(clock, ringingAlarmCount=ringingAlarmCount, & rc=rc)
call ESMF_ClockPrint(clock, options="currTime string", rc=rc)
! check if alarms are ringing if (ringingAlarmCount > 0) then print *, "number of ringing alarms = ", ringingAlarmCount do i = 1, NUMALARMS if (ESMF_AlarmIsRinging(alarm(i), rc=rc)) then
call ESMF_AlarmGet(alarm(i), name=name, rc=rc) print *, trim(name), " is ringing!"
! after processing alarm, turn it off call ESMF_AlarmRingerOff(alarm(i), rc=rc)
end if ! this alarm is ringing end do ! each ringing alarm endif ! ringing alarms end do ! timestep clock
This example shows how to destroy ESMF_Alarms and ESMF_Clocks.
call ESMF_AlarmDestroy(alarm(1), rc=rc)
call ESMF_AlarmDestroy(alarm(2), rc=rc)
call ESMF_ClockDestroy(clock, rc=rc)
! finalize ESMF framework call ESMF_Finalize(rc=rc)
end program ESMF_AlarmEx
The Alarm class is designed as a deep, dynamically allocatable class, based on a pointer type. This allows for both indirect and direct manipulation of alarms. Indirect alarm manipulation is where ESMF_Alarm API methods, such as ESMF_AlarmRingerOff(), are invoked on alarm references (pointers) returned from ESMF_Clock queries such as "return ringing alarms." Since the method is performed on an alarm reference, the actual alarm held by the clock is affected, not just a user's local copy. Direct alarm manipulation is the more common case where alarm API methods are invoked on the original alarm objects created by the user.
For consistency, the ESMF_Clock class is also designed as a deep, dynamically allocatable class.
An additional benefit from this approach is that Clocks and Alarms can be created and used from anywhere in a user's code without regard to the scope in which they were created. In constrast, statically created Alarms and Clocks would disappear if created within a user's routine that returns, whereas dynamically allocated Alarms and Clocks will persist until explicitly destroyed by the user.
INTERFACE:
interface assignment(=) alarm1 = alarm2ARGUMENTS:
type(ESMF_Alarm) :: alarm1 type(ESMF_Alarm) :: alarm2STATUS:
DESCRIPTION:
Assign alarm1 as an alias to the same ESMF_Alarm object in memory as alarm2. If alarm2 is invalid, then alarm1 will be equally invalid after the assignment.
The arguments are:
INTERFACE:
interface operator(==) if (alarm1 == alarm2) then ... endif OR result = (alarm1 == alarm2)RETURN VALUE:
logical :: resultARGUMENTS:
type(ESMF_Alarm), intent(in) :: alarm1 type(ESMF_Alarm), intent(in) :: alarm2DESCRIPTION:
Overloads the (==) operator for the ESMF_Alarm class. Compare two alarms for equality; return .true. if equal, .false. otherwise. Comparison is based on IDs, which are distinct for newly created alarms and identical for alarms created as copies.
If either side of the equality test is not in the ESMF_INIT_CREATED status an error will be logged. However, this does not affect the return value, which is .true. when both sides are in the same status, and .false. otherwise.
The arguments are:
INTERFACE:
interface operator(/=) if (alarm1 /= alarm2) then ... endif OR result = (alarm1 /= alarm2)RETURN VALUE:
logical :: resultARGUMENTS:
type(ESMF_Alarm), intent(in) :: alarm1 type(ESMF_Alarm), intent(in) :: alarm2DESCRIPTION:
Overloads the (/=) operator for the ESMF_Alarm class. Compare two alarms for inequality; return .true. if not equal, .false. otherwise. Comparison is based on IDs, which are distinct for newly created alarms and identical for alarms created as copies.
If either side of the equality test is not in the ESMF_INIT_CREATED status an error will be logged. However, this does not affect the return value, which is .true. when both sides are not in the same status, and .false. otherwise.
The arguments are:
INTERFACE:
! Private name; call using ESMF_AlarmCreate() function ESMF_AlarmCreateNew(clock, & ringTime, ringInterval, stopTime, ringDuration, ringTimeStepCount, & refTime, enabled, sticky, name, rc)RETURN VALUE:
type(ESMF_Alarm) :: ESMF_AlarmCreateNewARGUMENTS:
type(ESMF_Clock), intent(in) :: clock -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_Time), intent(in), optional :: ringTime type(ESMF_TimeInterval), intent(in), optional :: ringInterval type(ESMF_Time), intent(in), optional :: stopTime type(ESMF_TimeInterval), intent(in), optional :: ringDuration integer, intent(in), optional :: ringTimeStepCount type(ESMF_Time), intent(in), optional :: refTime logical, intent(in), optional :: enabled logical, intent(in), optional :: sticky character (len=*), intent(in), optional :: name integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Creates and sets the initial values in a new ESMF_Alarm.
In ESMF_DIRECTION_REVERSE (see Section 41.1), alarms ring in reverse, i.e., they begin ringing when they originally ended, and end ringing when they originally began.
The arguments are:
INTERFACE:
! Private name; call using ESMF_AlarmCreate() function ESMF_AlarmCreateCopy(alarm, rc)RETURN VALUE:
type(ESMF_Alarm) :: ESMF_AlarmCreateCopyARGUMENTS:
type(ESMF_Alarm), intent(in) :: alarm -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Creates a complete (deep) copy of a given ESMF_Alarm. The returned ESMF_Alarm copy is associated with the same ESMF_Clock as the original ESMF_Alarm. If desired, use ESMF_AlarmSet(...clock=...) to re-associate the ESMF_Alarm copy with a different ESMF_Clock.
The arguments are:
INTERFACE:
subroutine ESMF_AlarmDestroy(alarm, rc)ARGUMENTS:
type(ESMF_Alarm), intent(inout) :: alarm -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Releases resources associated with this ESMF_Alarm. Also removes this ESMF_Alarm from its associated ESMF_Clock's list of ESMF_Alarms (removes the ESMF_Alarm pointer from the list).
The arguments are:
INTERFACE:
subroutine ESMF_AlarmDisable(alarm, rc)ARGUMENTS:
type(ESMF_Alarm), intent(inout) :: alarm -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Disables an ESMF_Alarm.
The arguments are:
INTERFACE:
subroutine ESMF_AlarmEnable(alarm, rc)ARGUMENTS:
type(ESMF_Alarm), intent(inout) :: alarm -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Enables an ESMF_Alarm to function.
The arguments are:
INTERFACE:
subroutine ESMF_AlarmGet(alarm, & clock, ringTime, prevRingTime, ringInterval, stopTime, ringDuration, & ringTimeStepCount, timeStepRingingCount, ringBegin, ringEnd, & refTime, ringing, ringingOnPrevTimeStep, enabled, sticky, name, rc)ARGUMENTS:
type(ESMF_Alarm), intent(in) :: alarm -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_Clock), intent(out), optional :: clock type(ESMF_Time), intent(out), optional :: ringTime type(ESMF_Time), intent(out), optional :: prevRingTime type(ESMF_TimeInterval), intent(out), optional :: ringInterval type(ESMF_Time), intent(out), optional :: stopTime type(ESMF_TimeInterval), intent(out), optional :: ringDuration integer, intent(out), optional :: ringTimeStepCount integer, intent(out), optional :: timeStepRingingCount type(ESMF_Time), intent(out), optional :: ringBegin type(ESMF_Time), intent(out), optional :: ringEnd type(ESMF_Time), intent(out), optional :: refTime logical, intent(out), optional :: ringing logical, intent(out), optional :: ringingOnPrevTimeStep logical, intent(out), optional :: enabled logical, intent(out), optional :: sticky character (len=*), intent(out), optional :: name integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Gets one or more of an ESMF_Alarm's properties.
The arguments are:
INTERFACE:
function ESMF_AlarmIsEnabled(alarm, rc)RETURN VALUE:
logical :: ESMF_AlarmIsEnabledARGUMENTS:
type(ESMF_Alarm), intent(in) :: alarm -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Check if ESMF_Alarm is enabled.
The arguments are:
INTERFACE:
function ESMF_AlarmIsRinging(alarm, rc)RETURN VALUE:
logical :: ESMF_AlarmIsRingingARGUMENTS:
type(ESMF_Alarm), intent(in) :: alarm -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Check if ESMF_Alarm is ringing.
See also method ESMF_ClockGetAlarmList(clock, ESMF_ALARMLIST_RINGING, ...) to get a list of all ringing alarms belonging to an ESMF_Clock.
The arguments are:
INTERFACE:
function ESMF_AlarmIsSticky(alarm, rc)RETURN VALUE:
logical :: ESMF_AlarmIsStickyARGUMENTS:
type(ESMF_Alarm), intent(in) :: alarm -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Check if alarm is sticky.
The arguments are:
INTERFACE:
subroutine ESMF_AlarmNotSticky(alarm, & ringDuration, ringTimeStepCount, rc)ARGUMENTS:
type(ESMF_Alarm), intent(inout) :: alarm -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_TimeInterval), intent(in), optional :: ringDuration integer, intent(in), optional :: ringTimeStepCount integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Unset an ESMF_Alarm's sticky flag; once alarm is ringing, it turns itself off after ringDuration.
The arguments are:
INTERFACE:
subroutine ESMF_AlarmPrint(alarm, options, rc)ARGUMENTS:
type(ESMF_Alarm), intent(in) :: alarm character (len=*), intent(in), optional :: options integer, intent(out), optional :: rcDESCRIPTION:
Prints out an ESMF_Alarm's properties to stdout, in support
of testing and debugging. The options control the type of information
and level of detail.
The arguments are:
INTERFACE:
subroutine ESMF_AlarmRingerOff(alarm, rc)ARGUMENTS:
type(ESMF_Alarm), intent(inout) :: alarm -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Turn off an ESMF_Alarm; unsets ringing state. For a sticky alarm, this method must be called to turn off its ringing state. This is true for either ESMF_DIRECTION_FORWARD (default) or ESMF_DIRECTION_REVERSE. See Section 41.1.
The arguments are:
INTERFACE:
subroutine ESMF_AlarmRingerOn(alarm, rc)ARGUMENTS:
type(ESMF_Alarm), intent(inout) :: alarm -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Turn on an ESMF_Alarm; sets ringing state.
The arguments are:
INTERFACE:
subroutine ESMF_AlarmSet(alarm, & clock, ringTime, ringInterval, stopTime, ringDuration, & ringTimeStepCount, refTime, ringing, enabled, sticky, name, rc)ARGUMENTS:
type(ESMF_Alarm), intent(inout) :: alarm -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_Clock), intent(in), optional :: clock type(ESMF_Time), intent(in), optional :: ringTime type(ESMF_TimeInterval), intent(in), optional :: ringInterval type(ESMF_Time), intent(in), optional :: stopTime type(ESMF_TimeInterval), intent(in), optional :: ringDuration integer, intent(in), optional :: ringTimeStepCount type(ESMF_Time), intent(in), optional :: refTime logical, intent(in), optional :: ringing logical, intent(in), optional :: enabled logical, intent(in), optional :: sticky character (len=*), intent(in), optional :: name integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Sets/resets one or more of the properties of an ESMF_Alarm that was previously initialized via ESMF_AlarmCreate().
The arguments are:
INTERFACE:
subroutine ESMF_AlarmSticky(alarm, rc)ARGUMENTS:
type(ESMF_Alarm), intent(inout) :: alarm -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Set an ESMF_Alarm's sticky flag; once alarm is ringing, it remains ringing until ESMF_AlarmRingerOff() is called. There is an implicit limitation that in order to properly reverse timestep through a ring end time in ESMF_DIRECTION_REVERSE, that time must have already been traversed in the forward direction. This is due to the fact that an ESMF_Alarm cannot predict when user code will call ESMF_AlarmRingerOff(). An error message will be logged when this limitation is not satisfied.
The arguments are:
INTERFACE:
subroutine ESMF_AlarmValidate(alarm, rc)ARGUMENTS:
type(ESMF_Alarm), intent(in) :: alarm -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Performs a validation check on an ESMF_Alarm's properties. Must have a valid ringTime, set either directly or indirectly via ringInterval. See ESMF_AlarmCreate().
The arguments are:
INTERFACE:
function ESMF_AlarmWasPrevRinging(alarm, rc)RETURN VALUE:
logical :: ESMF_AlarmWasPrevRingingARGUMENTS:
type(ESMF_Alarm), intent(in) :: alarm -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Check if ESMF_Alarm was ringing on the previous clock timestep.
See also method ESMF_ClockGetAlarmList(clock, ESMF_ALARMLIST_PREVRINGING, ...) get a list of all alarms belonging to a ESMF_Clock that were ringing on the previous time step.
The arguments are:
INTERFACE:
function ESMF_AlarmWillRingNext(alarm, timeStep, rc)RETURN VALUE:
logical :: ESMF_AlarmWillRingNextARGUMENTS:
type(ESMF_Alarm), intent(in) :: alarm -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_TimeInterval), intent(in), optional :: timeStep integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Check if ESMF_Alarm will ring on the next clock timestep, either the current clock timestep or a passed-in timestep.
See also method ESMF_ClockGetAlarmList(clock, ESMF_ALARMLIST_NEXTRINGING, ...) to get a list of all alarms belonging to a ESMF_Clock that will ring on the next time step.
The arguments are:
ESMF Configuration Management is based on NASA DAO's
Inpak 90 package, a Fortran 90 collection of routines/functions
for accessing Resource Files in ASCII format.The package
is optimized for minimizing formatted I/O, performing all of its
string operations in memory using Fortran intrinsic functions.
The ESMF Configuration Management Package was evolved by Leonid Zaslavsky and Arlindo da Silva from Ipack90 package created by Arlindo da Silva at NASA DAO.
Back in the 70's Eli Isaacson wrote IOPACK in Fortran 66. In June of 1987 Arlindo da Silva wrote Inpak77 using Fortran 77 string functions; Inpak 77 is a vastly simplified IOPACK, but has its own goodies not found in IOPACK. Inpak 90 removes some obsolete functionality in Inpak77, and parses the whole resource file in memory for performance.
A Resource File (RF) is a text file consisting of list of label-value pairs. There is a limit of 250 characters per line and the Resource File can contain a maximum of 200 records. Each label should be followed by some data, the value. An example Resource File follows. It is the file used in the example below.
# This is an example Resource File. # It contains a list of <label,value> pairs. # The colon after the label is required. # The values after the label can be an list. # Multiple types are authorized. my_file_names: jan87.dat jan88.dat jan89.dat # all strings constants: 3.1415 25 # float and integer my_favorite_colors: green blue 022 # Or, the data can be a list of single value pairs. # It is simplier to retrieve data in this format: radius_of_the_earth: 6.37E6 parameter_1: 89 parameter_2: 78.2 input_file_name: dummy_input.netcdf # Or, the data can be located in a table using the following # syntax: my_table_name:: 1000 3000 263.0 925 3000 263.0 850 3000 263.0 700 3000 269.0 500 3000 287.0 400 3000 295.8 300 3000 295.8 ::
Note that the colon after the label is required and that the double colon is required to declare tabular data.
Resource files are intended for random access (except between ::'s in a table definition). This means that order in which a particular label-value pair is retreived is not dependent upon the original order of the pairs. The only exception to this, however, is when the same label appears multiple times within the Resource File.
This example/test code performs simple Config/Resource File routines. It does not include attaching a Config to a component. The important thing to remember there is that you can have one Config per component.
There are two methodologies for accessing data in a Resource File. This example will demonstrate both.
Note the API section contains a complete description of arguments in the methods/functions demonstrated in this example.
The following are the variable declarations used as arguments in the following code fragments. They represent the locals names for the variables listed in the Resource File (RF). Note they do not need to be the same.
character(ESMF_MAXSTR) :: fname ! config file name character*20 :: fn1, fn2, fn3, input_file ! strings to be read in integer :: rc ! error return code (0 is OK) integer :: i_n ! the first constant in the RF real :: param_1 ! the second constant in the RF real :: radius ! radius of the earth real :: table(7,3) ! an array to hold the table in the RF type(ESMF_Config) :: cf ! the Config itself
While there are two methodologies for accessing the data within a Resource File, there is only one way to create the initial Config and load its ASCII text into memory. This is the first step in the process.
Note that subsequent calls to ESMF_ConfigLoadFile will OVERWRITE the current Config NOT append to it. There is no means of appending to a Config.
cf = ESMF_ConfigCreate(rc=rc) ! Create the empty Config
fname = "myResourceFile.rc" ! Name the Resource File call ESMF_ConfigLoadFile(cf, fname, rc=rc) ! Load the Resource File ! into the empty Config
Remember, that the order in which a particular label/value pair is retrieved is not dependent upon the order which they exist within the Resource File.
call ESMF_ConfigGetAttribute(cf, radius, label='radius_of_the_earth:', & default=1.0, rc=rc)
Note that the colon must be included in the label string when using this methodology. It is also important to provide a default value in case the label does not exist in the file
This methodology works for all types. The following is an example of retrieving a string:
call ESMF_ConfigGetAttribute(cf, input_file, label='input_file_name:', & default="./default.nc", rc=rc)
The same code fragment can be used to demonstrate what happens when the label is not present. Note that "file_name" does not exist in the Resource File. The result of its abscense is the default value provided in the call.
call ESMF_ConfigGetAttribute(cf, input_file, label='file_name:', & default="./default.nc", rc=rc)
A second reminder that the order in which a particular label/value pair is retrieved is not dependent upon the order which they exist within the Resource File. The label used in this method allows the user to skip to any point in the file.
call ESMF_ConfigFindLabel(cf, 'constants:', rc=rc) ! Step a) Find the ! label
Two constants, radius and i_n, can now be retrieved without having to specify their label or use an array. They are also different types.
call ESMF_ConfigGetAttribute(cf, param_1, rc=rc) ! Step b) read in the ! first constant in ! the sequence call ESMF_ConfigGetAttribute(cf, i_n, rc=rc) ! Step c) read in the ! second constant in ! the sequence
This methodology also works with strings.
call ESMF_ConfigFindLabel(cf, 'my_file_names:', & rc=rc) ! Step a) find the label
call ESMF_ConfigGetAttribute(cf, fn1, & rc=rc) ! Step b) retrieve the 1st filename call ESMF_ConfigGetAttribute(cf, fn2, & rc=rc) ! Step c) retrieve the 2nd filename call ESMF_ConfigGetAttribute(cf, fn3, & rc=rc) ! Step d) retrieve the 3rd filename
To access tabular data, the user must use the multi-value method.
call ESMF_ConfigFindLabel(cf, 'my_table_name::', & rc=rc) ! Step a) Set the label location to the ! beginning of the table
Subsequently, call ESMF_ConfigNextLine() is used to move the location to the next row of the table. The example table in the Resource File contains 7 rows and 3 columns (7,3).
do i = 1, 7 call ESMF_ConfigNextLine(cf, rc=rc) ! Step b) Increment the rows do j = 1, 3 ! Step c) Fill in the table call ESMF_ConfigGetAttribute(cf, table(i,j), rc=rc) enddo enddo
The work with the configuration file cf is finalized by call to ESMF_ConfigDestroy():
call ESMF_ConfigDestroy(cf, rc=rc) ! Destroy the Config
INTERFACE:
interface assignment(=) config1 = config2ARGUMENTS:
type(ESMF_Config) :: config1 type(ESMF_Config) :: config2DESCRIPTION:
Assign config1 as an alias to the same ESMF Config object in memory as config2. If config2 is invalid, then config1 will be equally invalid after the assignment.
The arguments are:
INTERFACE:
type(ESMF_Config) function ESMF_ConfigCreate(rc)ARGUMENTS:
-- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer,intent(out), optional :: rcSTATUS:
DESCRIPTION:
Instantiates an ESMF_Config object for use in subsequent calls.
The arguments are:
INTERFACE:
subroutine ESMF_ConfigDestroy(config, rc)ARGUMENTS:
type(ESMF_Config), intent(inout) :: config -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Destroys the config object.
The arguments are:
INTERFACE:
subroutine ESMF_ConfigFindLabel(config, label, rc)ARGUMENTS:
type(ESMF_Config), intent(inout) :: config character(len=*), intent(in) :: label -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Finds the label (key) string in the config object.
Since the search is done by looking for a string, possibly multi-worded, in the whole Config object, it is important to use special conventions to distinguish labels from other words. This is done in the Resource File by using the DAO convention to finish line labels with a (:) and table labels with a double colon (::).
The arguments are:
INTERFACE:
subroutine ESMF_ConfigGetAttribute(config, <value>, & label, default, rc)ARGUMENTS:
type(ESMF_Config), intent(inout) :: config <value argument>, see below for supported values -- The following arguments require argument keyword syntax (e.g. rc=rc). -- character(len=*), intent(in), optional :: label character(len=*), intent(in), optional :: default integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Gets a value from the config object. When the value is a sequence of characters it will be terminated by the first white space.
Supported values for <value argument> are:
The arguments are:
INTERFACE:
subroutine ESMF_ConfigGetAttribute(config, <value list argument>, & count, label, default, rc)ARGUMENTS:
type(ESMF_Config), intent(inout) :: config <value list argument>, see below for values -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(in) optional :: count character(len=*), intent(in), optional :: label character(len=*), intent(in), optional :: default integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Gets a list of values from the config object.
Supported values for <value list argument> are:
The arguments are:
INTERFACE:
subroutine ESMF_ConfigGetChar(config, value, & label, default, rc)ARGUMENTS:
type(ESMF_Config), intent(inout) :: config character, intent(out) :: value -- The following arguments require argument keyword syntax (e.g. rc=rc). -- character(len=*), intent(in), optional :: label character, intent(in), optional :: default integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Gets a character value from the config object.
The arguments are:
INTERFACE:
subroutine ESMF_ConfigGetDim(config, lineCount, columnCount, & label, rc)ARGUMENTS:
type(ESMF_Config), intent(inout) :: config integer, intent(out) :: lineCount integer, intent(out) :: columnCount -- The following arguments require argument keyword syntax (e.g. rc=rc). -- character(len=*), intent(in), optional :: label integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Returns the number of lines in the table in lineCount and the maximum number of words in a table line in columnCount.
The arguments are:
INTERFACE:
integer function ESMF_ConfigGetLen(config, label, rc)ARGUMENTS:
type(ESMF_Config), intent(inout) :: config -- The following arguments require argument keyword syntax (e.g. rc=rc). -- character(len=*), intent(in), optional :: label integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Gets the length of the line in words by counting words disregarding types. Returns the word count as an integer.
The arguments are:
INTERFACE:
subroutine ESMF_ConfigLoadFile(config, filename, & delayout, unique, rc)ARGUMENTS:
type(ESMF_Config), intent(inout) :: config character(len=*), intent(in) :: filename -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_DELayout), intent(in), optional :: delayout logical, intent(in), optional :: unique integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Resource file with filename is loaded into memory.
The arguments are:
INTERFACE:
subroutine ESMF_ConfigNextLine(config, tableEnd, rc)ARGUMENTS:
type(ESMF_Config), intent(inout) :: config -- The following arguments require argument keyword syntax (e.g. rc=rc). -- logical, intent(out), optional :: tableEnd integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Selects the next line (for tables).
The arguments are:
INTERFACE:
subroutine ESMF_ConfigSetAttribute(config, <value argument>, & label, rc)ARGUMENTS:
type(ESMF_Config), intent(inout) :: config <value argument>, see below for supported values -- The following arguments require argument keyword syntax (e.g. rc=rc). -- character(len=*), intent(in), optional :: label integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Sets a value in the config object.
Supported values for <value argument> are:
The arguments are:
INTERFACE:
subroutine ESMF_ConfigValidate(config, & options, rc)ARGUMENTS:
type(ESMF_Config), intent(inout) :: config -- The following arguments require argument keyword syntax (e.g. rc=rc). -- character (len=*), intent(in), optional :: options integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Checks whether a config object is valid.
The arguments are:
The Log class consists of a variety of methods for writing error, warning, and informational messages to files. A default Log is created at ESMF initialization. Other Logs can be created later in the code by the user. Most Log methods take a Log as an optional argument and apply to the default Log when another Log is not specified. A set of standard return codes and associated messages are provided for error handling.
Log provides capabilities to store message entries in a buffer, which is flushed to a file, either when the buffer is full, or when the user calls an ESMF_LogFlush() method. Currently, the default is for the Log to flush after every ten entries. This can easily be changed by using the ESMF_LogSet() method and setting the maxElements property to another value. The ESMF_LogFlush() method is automatically called when the program exits by any means (program completion, halt on error, or when the Log is closed).
The user has the capability to abort the program on conditions such as an error or on a warning by using the ESMF_LogSet() method with the logmsgAbort argument. For example if the logmsgAbort array is set to (ESMF_LOGMSG_ERROR,ESMF_LOGMSG_WARNING), the program will stop on any and all warning or errors. When the logmsgAbort argument is set to ESMF_LOGMSG_ERROR, the program will only abort on errors. Lastly, the user can choose to never abort by using ESMF_LOGMSG_NONE; this is the default.
Log will automatically put the PET number into the Log. Also, the user can either specify ESMF_LOGKIND_SINGLE which writes all the entries to a single Log or ESMF_LOGKIND_MULTI which writes entries to multiple Logs according to the PET number. To distinguish Logs from each other when using ESMF_LOGKIND_MULTI, the PET number (in the format PETx.) will be prepended to the file name where x is the PET number.
Opening multiple log files and writing log messages from all the processors may affect the application performance while running on a large number of processors. For that reason, ESMF_LOGKIND_NONE is provided to switch off the Log capability. All the Log methods have no effect in the ESMF_LOGKIND_NONE mode.
A tracing capability may be enabled by setting the trace flag by using the ESMF_LogSet() method. When tracing is enabled, calls to methods such as ESMF_LogFoundError, ESMF_LogFoundAllocError, and ESMF_LogFoundDeallocError are logged in the default log file. This can result in voluminous output. It is typically used only around areas of code which are being debugged.
Other options that are planned for Log are to adjust the verbosity of output, and to optionally write to stdout instead of file(s).
The valid values are:
DESCRIPTION:
Specifies a single log file, multiple log files (one per PET), or no log files.
The type of this flag is:
type(ESMF_LogKind_Flag)
The valid values are:
DESCRIPTION:
Specifies a message level
The type of this flag is:
type(ESMF_LogMsg_Flag)
The valid values are:
Valid predefined named array constant values are:
By default ESMF_Initialize() opens a default Log in ESMF_LOGKIND_MULTI mode. ESMF handles the initialization and finalization of the default Log so the user can immediately start using it. If additional Log objects are desired, they must be explicitly created or opened using ESMF_LogOpen().
ESMF_LogOpen() requires a Log object and filename argument. Additionally, the user can specify single or multi Logs by setting the logkindflag property to ESMF_LOGKIND_SINGLE or ESMF_LOGKIND_MULTI. This is useful as the PET numbers are automatically added to the Log entries. A single Log will put all entries, regardless of PET number, into a single log while a multi Log will create multiple Logs with the PET number prepended to the filename and all entries will be written to their corresponding Log by their PET number.
By default, the Log file is not truncated at the start of a new run; it just gets appended each time. Future functionality may include an option to either truncate or append to the Log file.
In all cases where a Log is opened, a Fortran unit number is assigned to a specific Log. A Log is assigned an unused unit number using the algorithm described in the ESMF_IOUnitGet() method.
The user can then set or get options on how the Log should be used with the ESMF_LogSet() and ESMF_LogGet() methods. These are partially implemented at this time.
Depending on how the options are set, ESMF_LogWrite() either writes user messages directly to a Log file or writes to a buffer that can be flushed when full or by using the ESMF_LogFlush() method. The default is to flush after every ten entries because maxElements is initialized to ten (which means the buffer reaches its full state after every ten writes and then flushes).
A message filtering option may be set with ESMF_LogSet() so that only selected message types are actually written to the log. One key use of this feature is to allow placing informational log write requests into the code for debugging or tracing. Then, when the informational entries are not needed, the messages at that level may be turned off -- leaving only warning and error messages in the logs.
For every ESMF_LogWrite(), a time and date stamp is prepended to the Log entry. The time is given in microsecond precision. The user can call other methods to write to the Log. In every case, all methods eventually make a call implicitly to ESMF_LogWrite() even though the user may never explicitly call it.
When calling ESMF_LogWrite(), the user can supply an optional line, file and method. These arguments can be passed in explicitly or with the help of cpp macros. In the latter case, a define for an ESMF_FILENAME must be placed at the beginning of a file and a define for ESMF_METHOD must be placed at the beginning of each method. The user can then use the ESMF_CONTEXT cpp macro in place of line, file and method to insert the parameters into the method. The user does not have to specify line number as it is a value supplied by cpp.
An example of Log output is given below running with logkindflag property set to ESMF_LOGKIND_MULTI (default) using the default Log:
(Log file PET0.ESMF_LogFile)
20041105 163418.472210 INFO PET0 Running with ESMF Version 2.2.1
(Log file PET1.ESMF_LogFile)
20041105 163419.186153 ERROR PET1 ESMF_Field.F90 812 ESMF_FieldGet No Grid or Bad Grid attached to Field
The first entry shows date and time stamp. The time is given in microsecond precision. The next item shown is the type of message (INFO in this case). Next, the PET number is added. Lastly, the content is written.
The second entry shows something slightly different. In this case, we have an ERROR. The method name (ESMF_Field.F90) is automatically provided from the cpp macros as well as the line number (812). Then the content of the message is written.
When done writing messages, the default Log is closed by calling ESMF_LogFinalize() or ESMF_LogClose() for user created Logs. Both methods will release the assigned unit number.
! !PROGRAM: ESMF_LogErrEx - Log Error examples ! ! !DESCRIPTION: ! ! This program shows examples of Log Error writing !----------------------------------------------------------------------------- #include "ESMF.h" ! Macros for cpp usage ! File define #define ESMF_FILENAME "ESMF_LogErrEx.F90" ! Method define #define ESMF_METHOD "program ESMF_LogErrEx" #include "ESMF_LogMacros.inc" ! ESMF Framework module use ESMF use ESMF_TestMod implicit none ! return variables integer :: rc1, rc2, rc3, rcToTest, allocRcToTest, result type(ESMF_LOG) :: alog ! a log object that is not the default log type(ESMF_LogKind_Flag) :: logkindflag type(ESMF_Time) :: time type(ESMF_VM) :: vm integer, pointer :: intptr(:)
This example shows how to use the default Log. This example does not use cpp macros but does use multi Logs. A separate Log will be created for each PET.
! Initialize ESMF to initialize the default Log call ESMF_Initialize(vm=vm, defaultlogfilename="LogErrEx.Log", & logkindflag=ESMF_LOGKIND_MULTI, rc=rc1)
! LogWrite call ESMF_LogWrite("Log Write 2", ESMF_LOGMSG_INFO, rc=rc2)
! LogMsgSetError call ESMF_LogSetError(ESMF_RC_OBJ_BAD, msg="Convergence failure", & rcToReturn=rc2)
! LogMsgFoundError call ESMF_TimeSet(time, calkindflag=ESMF_CALKIND_NOCALENDAR) call ESMF_TimeSyncToRealTime(time, rc=rcToTest) if (ESMF_LogFoundError(rcToTest, msg="getting wall clock time", & rcToReturn=rc2)) then ! Error getting time. The previous call will have printed the error ! already into the log file. Add any additional error handling here. ! (This call is expected to provoke an error from the Time Manager.) endif ! LogMsgFoundAllocError allocate(intptr(10), stat=allocRcToTest) if (ESMF_LogFoundAllocError(allocRcToTest, msg="integer array", & rcToReturn=rc2)) then ! Error during allocation. The previous call will have logged already ! an error message into the log. endif deallocate(intptr)
! Open a Log named "Testlog.txt" associated with alog. call ESMF_LogOpen(alog, "TestLog.txt", rc=rc1)
%///////////////////////////////////////////////////////////// \begin{verbatim} ! LogWrite call ESMF_LogWrite("Log Write 2", ESMF_LOGMSG_INFO, & line=__LINE__, file=ESMF_FILENAME, & method=ESMF_METHOD, log=alog, rc=rc2)
! LogMsgSetError call ESMF_LogSetError(ESMF_RC_OBJ_BAD, msg="Interpolation Failure", & line=__LINE__, file=ESMF_FILENAME, & method=ESMF_METHOD, rcToReturn=rc2, log=alog)
! This is an example showing a query of the default Log. Please note that ! no Log is passed in the argument list, so the default Log will be used. call ESMF_LogGet(logkindflag=logkindflag, rc=rc3)
! This is an example setting a property of a Log that is not the default. ! It was opened in a previous example, and the handle for it must be ! passed in the argument list. call ESMF_LogSet(log=alog, logmsgAbort=(/ESMF_LOGMSG_ERROR/), rc=rc2)
! Close the user log. call ESMF_LogClose(alog, rc=rc3)
! Finalize ESMF to close the default log call ESMF_Finalize(rc=rc1)
The properties for a Log are set with the ESMF_LogSet() method and retrieved with the ESMF_LogGet() method.
Additionally, buffering is enabled. Buffering allows ESMF to manage output data streams in a desired way. Writing to the buffer is transparent to the user because all the Log entries are handled automatically by the ESMF_LogWrite() method. All the user has to do is specify the buffer size (the default is ten) by setting the maxElements property. Every time the ESMF_LogWrite() method is called, a LogEntry element is populated with the ESMF_LogWrite() information. When the buffer is full (i.e., when all the LogEntry elements are populated), the buffer will be flushed and all the contents will be written to file. If buffering is not needed, that is maxElements=1 or flushImmediately=ESMF_TRUE, the ESMF_LogWrite() method will immediately write to the Log file(s).
The following is a simplified UML diagram showing the structure of the Log class. See Appendix A, A Brief Introduction to UML, for a translation table that lists the symbols in the diagram and their meaning.
INTERFACE:
interface assignment(=) log1 = log2ARGUMENTS:
type(ESMF_Log) :: log1 type(ESMF_Log) :: log2DESCRIPTION:
Assign log1 as an alias to the same ESMF Log object in memory as log2. If log2 is invalid, then log1 will be equally invalid after the assignment.
The arguments are:
INTERFACE:
subroutine ESMF_LogClose(log, rc)ARGUMENTS:
type(ESMF_Log), intent(inout) :: log type(ESMF_KeywordEnforcer),optional::keywordEnforcer !must use keywords below integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
This routine closes the user log file(s) associated with log. If the log is not explicitly closed, it will be closed by ESMF_Finalize.
The arguments are:
INTERFACE:
subroutine ESMF_LogFlush(log, rc)ARGUMENTS:
type(ESMF_KeywordEnforcer),optional::keywordEnforcer !must use keywords below type(ESMF_Log), intent(inout), optional :: log integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
This subroutine flushes the file buffer associated with log.
The arguments are:
INTERFACE:
function ESMF_LogFoundAllocError(statusToCheck, & msg,line,file, & method,rcToReturn,log)RETURN VALUE:
logical :: ESMF_LogFoundAllocErrorARGUMENTS:
integer, intent(in) :: statusToCheck -- The following arguments require argument keyword syntax (e.g. rc=rc). -- character(len=*), intent(in), optional :: msg integer, intent(in), optional :: line character(len=*), intent(in), optional :: file character(len=*), intent(in), optional :: method integer, intent(out), optional :: rcToReturn type(ESMF_Log), intent(inout), optional :: logSTATUS:
DESCRIPTION:
This function returns .true. when a Fortran status code returned from a memory allocation indicates an allocation error. An ESMF predefined memory allocation error message will be added to the ESMF_Log along with a user added msg, line, file and method. Additionally, statusToCheck will be converted to rcToReturn.
The arguments are:
INTERFACE:
function ESMF_LogFoundDeallocError(statusToCheck, & msg,line,file, & method,rcToReturn,log)RETURN VALUE:
logical ::ESMF_LogFoundDeallocErrorARGUMENTS:
integer, intent(in) :: statusToCheck -- The following arguments require argument keyword syntax (e.g. rc=rc). -- character(len=*), intent(in), optional :: msg integer, intent(in), optional :: line character(len=*), intent(in), optional :: file character(len=*), intent(in), optional :: method integer, intent(out), optional :: rcToReturn type(ESMF_Log), intent(inout), optional :: logSTATUS:
DESCRIPTION:
This function returns .true. when a Fortran status code returned from a memory deallocation indicates an deallocation error. An ESMF predefined memory deallocation error message will be added to the ESMF_Log along with a user added msg, line, file and method. Additionally, statusToCheck will be converted to rcToReturn.
The arguments are:
INTERFACE:
function ESMF_LogFoundError(rcToCheck, & msg, line, file, method, & rcToReturn, log)RETURN VALUE:
logical :: ESMF_LogFoundErrorARGUMENTS:
integer, intent(in), optional :: rcToCheck -- The following arguments require argument keyword syntax (e.g. rc=rc). -- character(len=*), intent(in), optional :: msg integer, intent(in), optional :: line character(len=*), intent(in), optional :: file character(len=*), intent(in), optional :: method integer, intent(out), optional :: rcToReturn type(ESMF_Log), intent(inout), optional :: logSTATUS:
DESCRIPTION:
This function returns .true. for ESMF return codes that indicate an error. A predefined error message will added to the ESMF_Log along with a user added msg, line, file and method. Additionally, rcToReturn is set to rcToCheck.
The arguments are:
INTERFACE:
subroutine ESMF_LogOpen(log, filename, logkindflag, rc)ARGUMENTS:
type(ESMF_Log), intent(inout) :: log character(len=*), intent(in) :: filename type(ESMF_LogKind_Flag), intent(in), optional :: logkindflag integer, intent(out), optional :: rcDESCRIPTION:
This routine opens a file named filename and associates it with the ESMF_Log. If the incoming log is already a valid Log object, no new Log is opened and the Log argument remains unchanged.
The arguments are:
INTERFACE:
subroutine ESMF_LogSet(log, flush, & logmsgAbort, maxElements, logmsgList, & errorMask, trace, rc)ARGUMENTS:
type(ESMF_Log), intent(inout), optional :: log logical, intent(in), optional :: flush type(ESMF_LogMsg_Flag), intent(in), optional :: logmsgAbort(:) integer, intent(in), optional :: maxElements type(ESMF_LogMsg_Flag), intent(in), optional :: logmsgList(:) integer, intent(in), optional :: errorMask(:) logical, intent(in), optional :: trace integer, intent(out), optional :: rcDESCRIPTION:
This subroutine sets the properties for the Log object.
The arguments are:
INTERFACE:
subroutine ESMF_LogSetError(rcToCheck, & msg, line, file, method, & rcToReturn, log)ARGUMENTS:
integer, intent(in) :: rcToCheck -- The following arguments require argument keyword syntax (e.g. rc=rc). -- character(len=*), intent(in), optional :: msg integer, intent(in), optional :: line character(len=*), intent(in), optional :: file character(len=*), intent(in), optional :: method integer, intent(out), optional :: rcToReturn type(ESMF_Log), intent(inout), optional :: logSTATUS:
DESCRIPTION:
This subroutine sets the rcToReturn value to rcToCheck if rcToReturn is present and writes this error code to the ESMF_Log if an error is generated. A predefined error message will added to the ESMF_Log along with a user added msg, line, file and method.
The arguments are:
INTERFACE:
recursive subroutine ESMF_LogWrite(msg, logmsgFlag, & logmsgList, & ! DEPRECATED ARGUMENT line, file, method, log, rc)ARGUMENTS:
character(len=*), intent(in) :: msg type(ESMF_LogMsg_Flag),intent(in),optional :: logmsgFlag type(ESMF_LogMsg_Flag),intent(in),optional::logmsgList ! DEPRECATED ARG -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(in), optional :: line character(len=*), intent(in), optional :: file character(len=*), intent(in), optional :: method type(ESMF_Log), intent(inout),optional :: log integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
This subroutine writes to the file associated with an ESMF_Log. A message is passed in along with the logmsgFlag, line, file and method. If the write to the ESMF_Log is successful, the function will return a logical true. This function is the base function used by all the other ESMF_Log writing methods.
The arguments are:
The DELayout class provides an additional layer of abstraction on top of the Virtual Machine (VM) layer. DELayout does this by introducing DEs (Decomposition Elements) as logical resource units. The DELayout object keeps track of the relationship between its DEs and the resources of the associated VM object.
The relationship between DEs and VM resources (PETs (Persistent Execution Threads) and VASs (Virtual Address Spaces)) contained in a DELayout object is defined during its creation and cannot be changed thereafter. There are, however, a number of hint and specification arguments that can be used to shape the DELayout during its creation.
Contrary to the number of PETs and VASs contained in a VM object, which are fixed by the available resources, the number of DEs contained in a DELayout can be chosen freely to best match the computational problem or other design criteria. Creating a DELayout with less DEs than there are PETs in the associated VM object can be used to share resources between decomposed objects within an ESMF component. Creating a DELayout with more DEs than there are PETs in the associated VM object can be used to evenly partition the computation over the available resources.
The simplest case, however, is where the DELayout contains the same number of DEs as there are PETs in the associated VM context. In this case the DELayout may be used to re-label the hardware and operating system resources held by the VM. For instance, it is possible to order the resources so that specific DEs have best available communication paths. The DELayout will map the DEs to the PETs of the VM according to the resource details provided by the VM instance.
Furthermore, general DE to PET mapping can be used to offer computational resources with finer granularity than the VM does. The DELayout can be queried for computational and communication capacities of DEs and DE pairs, respectively. This information can be used to best utilize the DE resources when partitioning the computational problem. In combination with other ESMF classes, general DE to PET mapping can be used to realize cache blocking, communication hiding and dynamic load balancing.
Finally, the DELayout layer offers primitives that allow a work queue style dynamic load balancing between DEs.
DESCRIPTION:
Specifies which VM resource DEs are pinned to - i.e. PETs or VASs.
The type of this flag is:
type(ESMF_Pin_Flag)
The valid values are:
DESCRIPTION:
Reply when a PET offers to service a DE.
The type of this flag is:
type(ESMF_ServiceReply_Flag)
The valid values are:
The following examples demonstrate how to create, use and destroy DELayout objects.
Without specifying any of the optional parameters the created ESMF_DELayout defaults into having as many DEs as there are PETs in the associated VM object. Consequently the resulting DELayout describes a simple 1-to-1 DE to PET mapping.
delayout = ESMF_DELayoutCreate(rc=rc)
The default DE to PET mapping is simply:
DE 0 -> PET 0 DE 1 -> PET 1 ...
DELayout objects that are not used any longer should be destroyed.
call ESMF_DELayoutDestroy(delayout, rc=rc)
The optional vm argument can be provided to DELayoutCreate() to lower the method's overhead by the amount it takes to determine the current VM.
delayout = ESMF_DELayoutCreate(vm=vm, rc=rc)
By default all PETs of the associated VM will be considered. However, if the optional argument petList is present DEs will only be mapped against the PETs contained in the list. When the following example is executed on four PETs it creates a DELayout with four DEs by default that are mapped to the provided PETs in their given order. It is erroneous to specify PETs that are not part of the VM context on which the DELayout is defined.
delayout = ESMF_DELayoutCreate(petList=(/(i,i=petCount-1,1,-1)/), rc=rc)
Once the end of the petList has been reached the DE to PET mapping continues from the beginning of the list. For a 4 PET VM the above created DELayout will end up with the following DE to PET mapping:
DE 0 -> PET 3 DE 1 -> PET 2 DE 2 -> PET 1 DE 2 -> PET 3
The deCount argument can be used to specify the number of DEs. In this example a DELayout is created that contains four times as many DEs as there are PETs in the VM.
delayout = ESMF_DELayoutCreate(deCount=4*petCount, rc=rc)
Cyclic DE to PET mapping is the default. For 4 PETs this means:
DE 0, 4, 8, 12 -> PET 0 DE 1, 5, 9, 13 -> PET 1 DE 2, 6, 10, 14 -> PET 2 DE 3, 7, 11, 15 -> PET 3The default DE to PET mapping can be overridden by providing the deGrouping argument. This argument provides a positive integer group number for each DE in the DELayout. All of the DEs of a group will be mapped against the same PET. The actual group index is arbitrary (but must be positive) and its value is of no consequence.
delayout = ESMF_DELayoutCreate(deCount=4*petCount, & deGrouping=(/(i/4,i=0,4*petCount-1)/), rc=rc)
This will achieve blocked DE to PET mapping. For 4 PETs this means:
DE 0, 1, 2, 3 -> PET 0 DE 4, 5, 6, 7 -> PET 1 DE 8, 9, 10, 11 -> PET 2 DE 12, 13, 14, 15 -> PET 3
The quality of the partitioning expressed by the DE to PET mapping depends on the amount and quality of information provided during DELayout creation. In the following example the compWeights argument is used to specify relative computational weights for all DEs and communication weights for DE pairs are provided by the commWeights argument. The example assumes four DEs.
allocate(compWeights(4)) allocate(commWeights(4, 4)) ! setup compWeights and commWeights according to computational problem delayout = ESMF_DELayoutCreate(deCount=4, compWeights=compWeights, & commWeights=commWeights, rc=rc) deallocate(compWeights, commWeights)
The resulting DE to PET mapping depends on the specifics of the VM object and the provided compWeights and commWeights arrays.
Full control over the DE to PET mapping is provided via the petMap argument. This example maps the DEs to PETs in reverse order. In the 4-PET case this will result in the following mapping:
DE 0 -> PET 3 DE 1 -> PET 2 DE 2 -> PET 1 DE 3 -> PET 0
delayout = ESMF_DELayoutCreate(petMap=(/(i,i=petCount-1,0,-1)/), rc=rc)
The petMap argument gives full control over DE to PET mapping. The following example run on 4 or more PETs maps DEs to PETs according to the following table:
DE 0 -> PET 3 DE 1 -> PET 3 DE 2 -> PET 1 DE 3 -> PET 0 DE 4 -> PET 2 DE 5 -> PET 1 DE 6 -> PET 3 DE 7 -> PET 1
delayout = ESMF_DELayoutCreate(petMap=(/3, 3, 1, 0, 2, 1, 3, 1/), rc=rc)
The simplest case is a DELayout where there is exactly one DE for every PET. Of course this implies that the number of DEs equals the number of PETs. This special 1-to-1 DE-to-PET mapping is very common and many applications assume it. The following example shows how a DELayout can be queried about its mapping.
First a default DELayout is created where the number of DEs equals the number of PETs, and are associated 1-to-1.
delayout = ESMF_DELayoutCreate(rc=rc)
Next the DELayout is queried for the oneToOneFlag, and the user code makes a decision based on its value.
call ESMF_DELayoutGet(delayout, oneToOneFlag=oneToOneFlag, rc=rc) if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) if (.not. oneToOneFlag) then ! handle the unexpected case of not dealing with a 1-to-1 mapping else
1-to-1 mapping is guaranteed in this branch and the following code can work under the simplifying assumption that every PET holds exactly one DE:
allocate(localDeToDeMap(1)) call ESMF_DELayoutGet(delayout, localDeToDeMap=localDeToDeMap, rc=rc) if (rc /= ESMF_SUCCESS) finalrc=rc myDe = localDeToDeMap(1) deallocate(localDeToDeMap) if (finalrc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) endif
In general a DELayout may map any number (including zero) DEs against a single PET. The exact situation can be detected by querying the DELayout for the oneToOneFlag. If this flag comes back as .true. then the DELayout maps exactly one DE against each PET, but if it comes back as .false. the DELayout describes a more general DE-to-PET layout. The following example shows how code can be be written to work for a general DELayout.
First a DELayout is created with two more DEs than there are PETs. The DELayout will consequently map some DEs to the same PET.
delayout = ESMF_DELayoutCreate(deCount=petCount+2, rc=rc)
The first piece of information needed on each PET is the localDeCount. This number may be different on each PET and indicates how many DEs are mapped against the local PET.
call ESMF_DELayoutGet(delayout, localDeCount=localDeCount, rc=rc)
The DELayout can further be queried for a list of DEs that are held by the local PET. This information is provided by the localDeToDeMap argument. In ESMF a localDe is an index that enumerates the DEs that are associated with the local PET. In many cases the exact bounds of the localDe index range, e.g. , or does not matter, since it only affects how user code indexes into variables the user allocated, and therefore set the specific bounds. However, there are a few Array and Field level calls that take localDe input arguments. In all those cases where the localDe index variable is passed into an ESMF call as an input argument, it must be defined with a range starting at zero, i.e. .
For consistency with Array and Field, the following code uses a range for the localDe index variable, although it is not strictly necessary here:
allocate(localDeToDeMap(0:localDeCount-1)) call ESMF_DELayoutGet(delayout, localDeToDeMap=localDeToDeMap, rc=rc) if (rc /= ESMF_SUCCESS) finalrc=rc do localDe=0, localDeCount-1 workDe = localDeToDeMap(localDe) ! print *, "I am PET", localPET, " and I am working on DE ", workDe enddo deallocate(localDeToDeMap) if (finalrc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT)
The DELayout API includes two calls that can be used to easily implement work queue dynamic load balancing. The work load is broken up into DEs (more than there are PETs) and processed by the PETs. Load balancing is only possible for ESMF multi-threaded VMs and requires that DEs are pinned to VASs instead of the PETs (default). The following example will run for any VM and DELayout, however, load balancing will only occur under the mentioned conditions.
delayout = ESMF_DELayoutCreate(deCount=petCount+2, & pinflag=ESMF_PIN_DE_TO_VAS, rc=rc)
call ESMF_DELayoutGet(delayout, vasLocalDeCount=localDeCount, rc=rc) if (rc /= ESMF_SUCCESS) finalrc=rc allocate(localDeToDeMap(localDeCount)) call ESMF_DELayoutGet(delayout, vasLocalDeToDeMap=localDeToDeMap, rc=rc) if (rc /= ESMF_SUCCESS) finalrc=rc do i=1, localDeCount workDe = localDeToDeMap(i) print *, "I am PET", localPET, & " and I am offering service for DE ", workDe reply = ESMF_DELayoutServiceOffer(delayout, de=workDe, rc=rc) if (rc /= ESMF_SUCCESS) finalrc=rc if (reply == ESMF_SERVICEREPLY_ACCEPT) then ! process work associated with workDe print *, "I am PET", localPET, ", service offer for DE ", workDe, & " was accepted." call ESMF_DELayoutServiceComplete(delayout, de=workDe, rc=rc) if (rc /= ESMF_SUCCESS) finalrc=rc endif enddo deallocate(localDeToDeMap) if (finalrc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT)
The DELayout class is a light weight object. It stores the DE to PET and VAS mapping for all DEs within all PET instances and a list of local DEs for each PET instance. The DELayout does not store the computational and communication weights optionally provided as arguments to the create method. These hints are only used during create while they are available in user owned arrays.
INTERFACE:
interface assignment(=) delayout1 = delayout2ARGUMENTS:
type(ESMF_DELayout) :: delayout1 type(ESMF_DELayout) :: delayout2STATUS:
DESCRIPTION:
Assign delayout1 as an alias to the same ESMF DELayout object in memory as delayout2. If delayout2 is invalid, then delayout1 will be equally invalid after the assignment.
The arguments are:
INTERFACE:
interface operator(==) if (delayout1 == delayout2) then ... endif OR result = (delayout1 == delayout2)RETURN VALUE:
logical :: resultARGUMENTS:
type(ESMF_DELayout), intent(in) :: delayout1 type(ESMF_DELayout), intent(in) :: delayout2STATUS:
DESCRIPTION:
Test whether delayout1 and delayout2 are valid aliases to the same ESMF DELayout object in memory. For a more general comparison of two ESMF DELayouts, going beyond the simple alias test, the ESMF_DELayoutMatch() function (not yet implemented) must be used.
The arguments are:
INTERFACE:
interface operator(/=) if (delayout1 /= delayout2) then ... endif OR result = (delayout1 /= delayout2)RETURN VALUE:
logical :: resultARGUMENTS:
type(ESMF_DELayout), intent(in) :: delayout1 type(ESMF_DELayout), intent(in) :: delayout2STATUS:
DESCRIPTION:
Test whether delayout1 and delayout2 are not valid aliases to the same ESMF DELayout object in memory. For a more general comparison of two ESMF DELayouts, going beyond the simple alias test, the ESMF_DELayoutMatch() function (not yet implemented) must be used.
The arguments are:
INTERFACE:
! Private name; call using ESMF_DELayoutCreate() function ESMF_DELayoutCreateDefault(deCount, deGrouping, & pinflag, petList, vm, rc)RETURN VALUE:
type(ESMF_DELayout) :: ESMF_DELayoutCreateDefaultARGUMENTS:
-- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(in), optional :: deCount integer, target, intent(in), optional :: deGrouping(:) type(ESMF_Pin_Flag), intent(in), optional :: pinflag integer, target, intent(in), optional :: petList(:) type(ESMF_VM), intent(in), optional :: vm integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Create an ESMF_DELayout object on the basis of optionally provided restrictions. By default a DELayout with deCount equal to petCount will be created, each DE mapped to a single PET. However, the number of DEs as well grouping of DEs and PETs can be specified via the optional arguments.
The arguments are:
INTERFACE:
! Private name; call using ESMF_DELayoutCreate() function ESMF_DELayoutCreateFromPetMap(petMap, pinflag, & vm, rc)RETURN VALUE:
type(ESMF_DELayout) :: ESMF_DELayoutCreateFromPetMapARGUMENTS:
integer, intent(in) :: petMap(:) -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_Pin_Flag), intent(in), optional :: pinflag type(ESMF_VM), intent(in), optional :: vm integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Create an ESMF_DELayout with exactly specified DE to PET mapping.
This ESMF method must be called in unison by all PETs of the VM. Calling this method from a PET not part of the VM or not calling it from a PET that is part of the VM will result in undefined behavior. ESMF does not guard against violation of the unison requirement. The call is not collective, there is no communication between PETs.
The arguments are:
INTERFACE:
subroutine ESMF_DELayoutDestroy(delayout, rc)ARGUMENTS:
type(ESMF_DELayout), intent(inout) :: delayout -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Destroy an ESMF_DELayout object.
The arguments are:
INTERFACE:
subroutine ESMF_DELayoutGet(delayout, vm, deCount, petMap, & vasMap, oneToOneFlag, pinflag, localDeCount, localDeToDeMap, & localDeList, & ! DEPRECATED ARGUMENT vasLocalDeCount, vasLocalDeToDeMap, & vasLocalDeList, & ! DEPRECATED ARGUMENT rc)ARGUMENTS:
type(ESMF_DELayout), intent(in) :: delayout -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_VM), intent(out), optional :: vm integer, intent(out), optional :: deCount integer, target, intent(out), optional :: petMap(:) integer, target, intent(out), optional :: vasMap(:) logical, intent(out), optional :: oneToOneFlag type(ESMF_Pin_Flag), intent(out), optional :: pinflag integer, intent(out), optional :: localDeCount integer, target, intent(out), optional :: localDeToDeMap(:) integer, target, intent(out), optional :: localDeList(:) !DEPRECATED ARG integer, intent(out), optional :: vasLocalDeCount integer, target, intent(out), optional :: vasLocalDeToDeMap(:) integer, target, intent(out), optional :: vasLocalDeList(:) !DEPRECATED ARG integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Access to DELayout information.
The arguments are:
INTERFACE:
subroutine ESMF_DELayoutPrint(delayout, rc)ARGUMENTS:
type(ESMF_DELayout), intent(in) :: delayout -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Prints internal information about the specified ESMF_DELayout
object to stdout.
The arguments are:
INTERFACE:
recursive subroutine ESMF_DELayoutServiceComplete(delayout, de, rc)ARGUMENTS:
type(ESMF_DELayout), intent(in) :: delayout integer, intent(in) :: de -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
The PET who's service offer was accepted for de must use ESMF_DELayoutServiceComplete to close the service window.
The arguments are:
INTERFACE:
recursive function ESMF_DELayoutServiceOffer(delayout, de, rc)RETURN VALUE:
type(ESMF_ServiceReply_Flag) :: ESMF_DELayoutServiceOfferARGUMENTS:
type(ESMF_DELayout), intent(in) :: delayout integer, intent(in) :: de -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Offer service for a DE in the ESMF_DELayout object. This call together with ESMF_DELayoutServiceComplete() provides the synchronization primitives between the PETs of an ESMF multi-threaded VM necessary for dynamic load balancing via a work queue approach.
The calling PET will either receive ESMF_SERVICEREPLY_ACCEPT if the service offer has been accepted by DELayout or ESMF_SERVICEREPLY_DENY if the service offer was denied. The service offer paradigm is different from a simple mutex approach in that the DELayout keeps track of the number of service offers issued for each DE by each PET and accepts only one PET's offer for each offer increment. This requires that all PETs use ESMF_DELayoutServiceOffer() in unison. See section 45.2.2 for the potential return values.
The arguments are:
INTERFACE:
subroutine ESMF_DELayoutValidate(delayout, rc)ARGUMENTS:
type(ESMF_DELayout), intent(in) :: delayout -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Validates that the delayout is internally consistent. The method returns an error code if problems are found.
The arguments are:
The ESMF VM (Virtual Machine) class is a generic representation of hardware and system software resources. There is exactly one VM object per ESMF Component, providing the execution environment for the Component code. The VM class handles all resource management tasks for the Component class and provides a description of the underlying configuration of the compute resources used by a Component.
In addition to resource description and management, the VM class offers the lowest level of ESMF communication methods. The VM communication calls are very similar to MPI. Data references in VM communication calls must be provided as raw, language specific, one-dimensional, contiguous data arrays. The similarity between VM and MPI communication calls is striking and there are many equivalent point-to-point and collective communication calls. However, unlike MPI, the VM communication calls support communication between threaded PETs in a completely transparent fashion.
Many ESMF applications do not interact with the VM class directly very much. The resource management aspect is wrapped completely transparent into the ESMF Component concept. Often the only reason that user code queries a Component object for the associated VM object is to inquire about resource information, such as the localPet or the petCount. Further, for most applications the use of higher level communication APIs, such as provided by Array and Field, are much more convenient than using the low level VM communication calls.
The basic elements of a VM are called PETs, which stands for Persistent Execution Threads. These are equivalent to OS threads with a lifetime of at least that of the associated component. All VM functionality is expressed in terms of PETs. In the simplest, and most common case, a PET is equivalent to an MPI process. However, ESMF also supports multi-threading, where multiple PETs run as Pthreads inside the same virtual address space (VAS).
The resource management functions of the VM class become visible when a component, or the driver code, creates sub-components. Section 14.4.5 discusses this aspect from the Superstructure perspective and provides links to the relevant Component examples in the documentation.
There are two parts to resource management, the parent and the child. When the parent component creates a child component, the parent VM object provides the resources on which the child is created with ESMF_GridCompCreate() or ESMF_CplCompCreate(). The optional petList argument to these calls limits the resources that the parent gives to a specific child. The child component, may specify - during its optional ESMF_<Grid/Cpl>CompSetVM() method - how it wants to arrange the inherited resources in its own VM. After this, all standard ESMF methods of the Component, including ESMF_<Grid/Cpl>CompSetServices(), will execute in the child VM. Notice that the ESMF_<Grid/Cpl>CompSetVM() routine, although part of the child Component, must execute before the child VM has been started up. It runs in the parent VM context. The child VM is created and started up just before the user-written set services routine, specified as an argument to ESMF_<Grid/Cpl>CompSetServices(), is entered.
The concept of the ESMF Virtual Machine (VM) is so fundamental to the framework that every ESMF application uses it. However, for many user applications the VM class is transparently hidden behind the ESMF Component concept and higher data classes (e.g. Array, Field). The interaction between user code and VM is often only indirect. The following examples provide an overview of where the VM class can come into play in user code.
This complete example program demonstrates the simplest ESMF application, consisting of only a main program without any Components. The global VM, which is automatically created during the ESMF_Initialize() call, is obtained using two different methods. First the global VM will be returned by ESMF_Initialize() if the optional vm argument is specified. The example uses the VM object obtained this way to call the VM print method. Second, the global VM can be obtained anywhere in the user application using the ESMF_VMGetGlobal() call. The identical VM is returned and several VM query methods are called to inquire about the associated resources.
program ESMF_VMDefaultBasicsEx #include "ESMF.h" use ESMF use ESMF_TestMod implicit none ! local variables integer:: rc type(ESMF_VM):: vm integer:: localPet, petCount, peCount, ssiId, vas
call ESMF_Initialize(vm=vm, defaultlogfilename="VMDefaultBasicsEx.Log", & logkindflag=ESMF_LOGKIND_MULTI, rc=rc) ! Providing the optional vm argument to ESMF_Initialize() is one way of ! obtaining the global VM.
call ESMF_VMPrint(vm, rc=rc)
call ESMF_VMGetGlobal(vm=vm, rc=rc) ! Calling ESMF_VMGetGlobal() anywhere in the user application is the other ! way to obtain the global VM object.
call ESMF_VMGet(vm, localPet=localPet, petCount=petCount, peCount=peCount, & rc=rc) ! The VM object contains information about the associated resources. If the ! user code requires this information it must query the VM object.
print *, "This PET is localPet: ", localPet print *, "of a total of ",petCount," PETs in this VM." print *, "There are ", peCount," PEs referenced by this VM" call ESMF_VMGet(vm, localPet, peCount=peCount, ssiId=ssiId, vas=vas, rc=rc)
print *, "This PET is executing in virtual address space (VAS) ", vas print *, "located on single system image (SSI) ", ssiId print *, "and is associated with ", peCount, " PEs."
end program
Sometimes user code requires access to the MPI communicator, e.g. to support legacy code that contains explict MPI communication calls. The correct way of wrapping such code into ESMF is to obtain the MPI intra-communicator out of the VM object. In order not to interfere with ESMF communications it is advisable to duplicate the communicator before using it in user-level MPI calls. In this example the duplicated communicator is used for a user controlled MPI_Barrier().
integer:: mpic
integer:: mpic2
call ESMF_VMGet(vm, mpiCommunicator=mpic, rc=rc) ! The returned MPI communicator spans the same MPI processes that the VM ! is defined on.
call MPI_Comm_dup(mpic, mpic2, ierr) ! Duplicate the MPI communicator not to interfere with ESMF communications. ! The duplicate MPI communicator can be used in any MPI call in the user ! code. Here the MPI_Barrier() routine is called. call MPI_Barrier(mpic2, ierr)
It is possible to nest an ESMF application inside a user application that explicitly calls MPI_Init() and MPI_Finalize(). The ESMF_Initialize() call automatically checks whether MPI has already been initialized, and if so does not call MPI_Init() internally. On the finalize side, ESMF_Finalize() can be instructed to not call MPI_Finalize(), making it the responsibility of the outer code to finalize MPI.
call MPI_Init(ierr) ! User code initializes MPI.
call ESMF_Initialize(defaultlogfilename="VMUserMpiEx.Log", & logkindflag=ESMF_LOGKIND_MULTI, rc=rc) ! ESMF_Initialize() does not call MPI_Init() if it finds MPI initialized.
call ESMF_Finalize(endflag=ESMF_END_KEEPMPI, rc=rc) ! Calling with endflag=ESMF_END_KEEPMPI instructs ESMF_Finalize() to keep ! MPI active.
call MPI_Finalize(ierr) ! It is the responsibility of the outer user code to finalize MPI.
The previous example demonstrated that it is possible to nest an ESMF application, i.e. ESMF_Initialize()...ESMF_Finalize() inside MPI_Init()...MPI_Finalize(). It is not necessary that all MPI ranks enter the ESMF application. The following example shows how the user code can pass an MPI communicator to ESMF_Initialize(), and enter the ESMF application on a subset of MPI ranks.
call MPI_Init(ierr) ! User code initializes MPI.
call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr) ! User code determines the local rank.
! User code prepares MPI communicator "esmfComm" that only contains ! rank 0 and 1.
if (rank < 2) then call ESMF_Initialize(mpiCommunicator=esmfComm, & defaultlogfilename="VMUserMpiCommEx.Log", & logkindflag=ESMF_LOGKIND_MULTI, rc=rc) ! Only call ESMF_Initialize() on rank 0 and 1, passing the prepared MPI ! communicator that spans these ranks.
call ESMF_Finalize(endflag=ESMF_END_KEEPMPI, rc=rc) ! Finalize ESMF without finalizing MPI. The user application will call ! MPI_Finalize() on all ranks.
endif
call MPI_Finalize(ierr) ! User code finalizes MPI.
The VM layer provides MPI-like point-to-point communication. Use ESMF_VMSend() and ESMF_VMRecv() to pass data between two PETs. The following code sends data from PET 'src' and receives it on PET 'dst'. Both PETs must be part of the same VM. The sendData and recvData arguments must be 1-dimensional arrays.
if (localPet==src) & call ESMF_VMSend(vm, sendData=localData, count=count, dstPet=dst, rc=rc)
if (localPet==dst) & call ESMF_VMRecv(vm, recvData=localData, count=count, srcPet=src, rc=rc)
The VM layer provides MPI-like collective communication. ESMF_VMScatter() scatters data located on root PET across all the PETs of the VM. ESMF_VMGather() provides the opposite operation, gathering data from all the PETs of the VM onto root PET.
call ESMF_VMScatter(vm, sendData=array1, recvData=array2, count=nsize, & rootPet=scatterRoot, rc=rc) ! Both sendData and recvData must be 1-d arrays.
call ESMF_VMGather(vm, sendData=array2, recvData=array1, count=nsize, & rootPet=gatherRoot, rc=rc) ! Both sendData and recvData must be 1-d arrays.
Use ESMF_VMAllReduce() to reduce data distributed across the PETs of a VM into a result vector, returned on all the PETs. Further, use ESMF_VMAllFullReduce() to reduce the data into a single scalar returned on all PETs.
call ESMF_VMAllReduce(vm, sendData=array1, recvData=array2, count=nsize, & reduceflag=ESMF_REDUCE_SUM, rc=rc) ! Both sendData and recvData must be 1-d arrays. Reduce distributed ! sendData element by element into recvData and return in on all PETs.
call ESMF_VMAllFullReduce(vm, sendData=array1, recvData=result, & count=nsize, reduceflag=ESMF_REDUCE_SUM, rc=rc) ! sendData must be 1-d array. Fully reduce the distributed sendData ! into a single scalar and return it in recvData on all PETs.
The following example shows the role that the VM plays in connection with ESMF Components. A single Component is created in the main program. Through the optional petList argument the driver code specifies that only resources associated with PET 0 are given to the gcomp object.
When the Component code is invoked through the standard ESMF Component methods Initialize, Run, or Finalize the Component's VM is automatically entered. Inside of the user-written Component code the Component VM can be obtained by querying the Component object. The VM object will indicate that only a single PET is executing the Component code.
module ESMF_VMComponentEx_gcomp_mod
recursive subroutine mygcomp_init(gcomp, istate, estate, clock, rc) type(ESMF_GridComp) :: gcomp type(ESMF_State) :: istate, estate type(ESMF_Clock) :: clock integer, intent(out) :: rc ! local variables type(ESMF_VM):: vm ! get this Component's vm call ESMF_GridCompGet(gcomp, vm=vm) ! the VM object contains information about the execution environment of ! the Component call ESMF_VMPrint(vm, rc=rc) rc = 0 end subroutine !-------------------------------------------------------------- recursive subroutine mygcomp_run(gcomp, istate, estate, clock, rc) type(ESMF_GridComp) :: gcomp type(ESMF_State) :: istate, estate type(ESMF_Clock) :: clock integer, intent(out) :: rc ! local variables type(ESMF_VM):: vm ! get this Component's vm call ESMF_GridCompGet(gcomp, vm=vm) ! the VM object contains information about the execution environment of ! the Component call ESMF_VMPrint(vm, rc=rc) rc = 0 end subroutine !-------------------------------------------------------------- recursive subroutine mygcomp_final(gcomp, istate, estate, clock, rc) type(ESMF_GridComp) :: gcomp type(ESMF_State) :: istate, estate type(ESMF_Clock) :: clock integer, intent(out) :: rc ! local variables type(ESMF_VM):: vm ! get this Component's vm call ESMF_GridCompGet(gcomp, vm=vm) ! the VM object contains information about the execution environment of ! the Component call ESMF_VMPrint(vm, rc=rc) rc = 0 end subroutine !-------------------------------------------------------------- end module
program ESMF_VMComponentEx #include "ESMF.h" use ESMF use ESMF_TestMod use ESMF_VMComponentEx_gcomp_mod implicit none ! local variables
gcomp = ESMF_GridCompCreate(petList=(/0/), rc=rc)
call ESMF_GridCompSetServices(gcomp, mygcomp_register, rc=rc)
call ESMF_GridCompInitialize(gcomp, rc=rc)
call ESMF_GridCompRun(gcomp, rc=rc)
call ESMF_GridCompFinalize(gcomp, rc=rc)
call ESMF_GridCompDestroy(gcomp, rc=rc)
call ESMF_Finalize(rc=rc)
end program
The VM class provides an additional layer of abstraction on top of the POSIX machine model, making it suitable for HPC applications. There are four key aspects the VM class deals with.
Definition of terms used in the diagram
The POSIX machine abstraction, while a very powerful concept, needs augmentation when applied to HPC applications. Key elements of the POSIX abstraction are processes, which provide virtually unlimited resources (memory, I/O, sockets, ...) to possibly multiple threads of execution. Similarly POSIX threads create the illusion that there is virtually unlimited processing power available to each POSIX process. While the POSIX abstraction is very suitable for many multi-user/multi-tasking applications that need to share limited physical resources, it does not directly fit the HPC workload where over-subscription of resources is one of the most expensive modes of operation.
ESMF's virtual machine abstraction is based on the POSIX machine model but holds additional information about the available physical processing units in terms of Processing Elements (PEs). A PE is the smallest physical processing unit and encapsulates the hardware details (Cores, CPUs and SSIs).
There is exactly one physical machine layout for each application, and all VM instances have access to this information. The PE is the smallest processing unit which, in today's microprocessor technology, corresponds to a single Core. Cores are arranged in CPUs which in turn are arranged in SSIs. The setup of the physical machine layout is part of the ESMF initialization process.
On top of the PE concept the key abstraction provided by the VM is the PET. All user code is executed by PETs while OS and hardware details are hidden. The VM class contains a number of methods which allow the user to prescribe how the PETs of a desired virtual machine should be instantiated on the OS level and how they should map onto the hardware. This prescription is kept in a private virtual machine plan object which is created at the same time the associated component is being created. Each time component code is entered through one of the component's registered top-level methods (Initialize/Run/Finalize), the virtual machine plan along with a pointer to the respective user function is used to instantiate the user code on the PETs of the associated VM in form of single- or multi-threaded POSIX processes.
The process of starting, entering, exiting and shutting down a VM is very transparent, all spawning and joining of threads is handled by VM methods "behind the scenes". Furthermore, fundamental synchronization and communication primitives are provided on the PET level through a uniform API, hiding details related to the actual instantiation of the participating PETs.
Within a VM object each PE of the physical machine maps to 0 or 1 PETs. Allowing unassigned PEs provides a means to prevent over-subscription between multiple concurrently running virtual machines. Similarly a maximum of one PET per PE prevents over-subscription within a single VM instance. However, over-subscription is possible by subscribing PETs from different virtual machines to the same PE. This type of over-subscription can be desirable for PETs associated with IO work loads expected to be used infrequently and to block often on IO requests.
On the OS level each PET of a VM object is represented by a POSIX thread (Pthread) either belonging to a single- or multi-threaded process and maps to at least 1 PE of the physical machine, ensuring its execution. Mapping a single PET to multiple PEs provides resources for user-level multi-threading, in which case the user code inquires how many PEs are associated with its PET and if there are multiple PEs available the user code can spawn an equal number of threads (e.g. OpenMP) without risking over-subscription. Typically these user spawned threads are short-lived and used for fine-grained parallelization in form of TETs. All PEs mapped against a single PET must be part of a unique SSI in order to allow user-level multi-threading!
In addition to discovering the physical machine the ESMF initialization process sets up the default global virtual machine. This VM object, which is the ultimate parent of all VMs created during the course of execution, contains as many PETs as there are PEs in the physical machine. All of its PETs are instantiated in form of single-threaded MPI processes and a 1:1 mapping of PETs to PEs is used for the default global VM.
The VM design and implementation is based on the POSIX process and thread model as well as the MPI-1.2 standard. As a consequence of the latter standard the number of processes is static during the course of execution and is determined at start-up. The VM implementation further requires that the user starts up the ESMF application with as many MPI processes as there are PEs in the available physical machine using the platform dependent mechanism to ensure proper process placement.
All MPI processes participating in a VM are grouped together by means of an MPI_Group object and their context is defined via an MPI_Comm object (MPI intra-communicator). The PET local process id within each virtual machine is equal to the MPI_Comm_rank in the local MPI_Comm context whereas the PET process id is equal to the MPI_Comm_rank in MPI_COMM_WORLD. The PET process id is used within the VM methods to determine the virtual memory space a PET is operating in.
In order to provide a migration path for legacy MPI-applications the VM offers accessor functions to its MPI_Comm object. Once obtained this object may be used in explicit user-code MPI calls within the same context.
INTERFACE:
interface assignment(=) vm1 = vm2ARGUMENTS:
type(ESMF_VM) :: vm1 type(ESMF_VM) :: vm2STATUS:
DESCRIPTION:
Assign vm1 as an alias to the same ESMF VM object in memory as vm2. If vm2 is invalid, then vm1 will be equally invalid after the assignment.
The arguments are:
INTERFACE:
interface operator(==) if (vm1 == vm2) then ... endif OR result = (vm1 == vm2)RETURN VALUE:
logical :: resultARGUMENTS:
type(ESMF_VM), intent(in) :: vm1 type(ESMF_VM), intent(in) :: vm2STATUS:
DESCRIPTION:
Test whether vm1 and vm2 are valid aliases to the same ESMF VM object in memory. For a more general comparison of two ESMF VMs, going beyond the simple alias test, the ESMF_VMMatch() function (not yet implemented) must be used.
The arguments are:
INTERFACE:
interface operator(/=) if (vm1 /= vm2) then ... endif OR result = (vm1 /= vm2)RETURN VALUE:
logical :: resultARGUMENTS:
type(ESMF_VM), intent(in) :: vm1 type(ESMF_VM), intent(in) :: vm2STATUS:
DESCRIPTION:
Test whether vm1 and vm2 are not valid aliases to the same ESMF VM object in memory. For a more general comparison of two ESMF VMs, going beyond the simple alias test, the ESMF_VMMatch() function (not yet implemented) must be used.
The arguments are:
INTERFACE:
subroutine ESMF_VMAllFullReduce(vm, sendData, recvData, & count, reduceflag, syncflag, commhandle, rc)ARGUMENTS:
type(ESMF_VM), intent(in) :: vm <type>(ESMF_KIND_<kind>), target, intent(in) :: sendData(:) <type>(ESMF_KIND_<kind>), intent(out) :: recvData integer, intent(in) :: count type(ESMF_Reduce_Flag), intent(in) :: reduceflag -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_Sync_Flag), intent(in), optional :: syncflag type(ESMF_CommHandle), intent(out), optional :: commhandle integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Collective ESMF_VM communication call that reduces a contiguous data
array of <type><kind> across the ESMF_VM object
into a single value of the same <type><kind>. The result is
returned on all PETs. Different reduction operations can be specified.
This method is overloaded for: ESMF_TYPEKIND_I4,
ESMF_TYPEKIND_R4, ESMF_TYPEKIND_R8.
TODO: The current version of this method does not provide an
implementation of the non-blocking feature. When calling this
method with syncflag = ESMF_SYNC_NONBLOCKING error code
ESMF_RC_NOT_IMPL will be returned and an error will be
logged.
The arguments are:
INTERFACE:
subroutine ESMF_VMAllGather(vm, sendData, recvData, count, & syncflag, commhandle, rc)ARGUMENTS:
type(ESMF_VM), intent(in) :: vm <type>(ESMF_KIND_<kind>), target, intent(in) :: sendData(:) <type>(ESMF_KIND_<kind>), target, intent(out) :: recvData(:) integer, intent(in) :: count -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_Sync_Flag), intent(in), optional :: syncflag type(ESMF_CommHandle), intent(out), optional :: commhandle integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Collective ESMF_VM communication call that gathers contiguous data
from all PETs of an ESMF_VM object into an array on all PETs.
This method is overloaded for:
ESMF_TYPEKIND_I4,
ESMF_TYPEKIND_R4, ESMF_TYPEKIND_R8,
ESMF_TYPEKIND_LOGICAL.
The arguments are:
INTERFACE:
subroutine ESMF_VMAllGatherV(vm, sendData, sendCount, & recvData, recvCounts, recvOffsets, syncflag, commhandle, rc)ARGUMENTS:
type(ESMF_VM), intent(in) :: vm <type>(ESMF_KIND_<kind>), target, intent(in) :: sendData(:) integer, intent(in) :: sendCount <type>(ESMF_KIND_<kind>), target, intent(out) :: recvData(:) integer, intent(in) :: recvCounts(:) integer, intent(in) :: recvOffsets(:) -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_Sync_Flag), intent(in), optional :: syncflag type(ESMF_CommHandle), intent(out), optional :: commhandle integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Collective ESMF_VM communication call that gathers contiguous data
from all PETs of an ESMF_VM object into an array on all PETs.
This method is overloaded for: ESMF_TYPEKIND_I4,
ESMF_TYPEKIND_R4, ESMF_TYPEKIND_R8.
TODO: The current version of this method does not provide an
implementation of the non-blocking feature. When calling this
method with syncflag = ESMF_SYNC_NONBLOCKING error code
ESMF_RC_NOT_IMPL will be returned and an error will be
logged.
The arguments are:
INTERFACE:
subroutine ESMF_VMAllReduce(vm, sendData, recvData, count, & reduceflag, syncflag, commhandle, rc)ARGUMENTS:
type(ESMF_VM), intent(in) :: vm <type>(ESMF_KIND_<kind>), target, intent(in) :: sendData(:) <type>(ESMF_KIND_<kind>), target, intent(out) :: recvData(:) integer, intent(in) :: count type(ESMF_Reduce_Flag), intent(in) :: reduceflag -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_Sync_Flag), intent(in), optional :: syncflag type(ESMF_CommHandle), intent(out), optional :: commhandle integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Collective ESMF_VM communication call that reduces a contiguous data
array across the ESMF_VM object into a contiguous data array of the
same <type><kind>. The result array is returned on all PETs.
Different reduction operations can be specified.
This method is overloaded for: ESMF_TYPEKIND_I4,
ESMF_TYPEKIND_R4, ESMF_TYPEKIND_R8.
TODO: The current version of this method does not provide an
implementation of the non-blocking feature. When calling this
method with syncflag = ESMF_SYNC_NONBLOCKING error code
ESMF_RC_NOT_IMPL will be returned and an error will be
logged.
The arguments are:
INTERFACE:
subroutine ESMF_VMAllToAll(vm, sendData, sendCount, & recvData, recvCount, syncflag, & commhandle, rc)ARGUMENTS:
type(ESMF_VM), intent(in) :: vm <type>(ESMF_KIND_<kind>), target, intent(in) :: sendData(:) integer, intent(in) :: sendCount <type>(ESMF_KIND_<kind>), target, intent(out) :: recvData(:) integer, intent(in) :: recvCount -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_Sync_Flag), intent(in), optional :: syncflag type(ESMF_CommHandle), intent(out), optional :: commhandle integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Collective ESMF_VM communication call that performs a total exchange
operation, sending pieces of the contiguous data buffer semdData to
all other PETs while receiving data into the contiguous data buffer
recvData from all other PETs.
This method is overloaded for: ESMF_TYPEKIND_I4,
ESMF_TYPEKIND_R4, ESMF_TYPEKIND_R8.
TODO: The current version of this method does not provide an
implementation of the non-blocking feature. When calling this
method with syncflag = ESMF_SYNC_NONBLOCKING error code
ESMF_RC_NOT_IMPL will be returned and an error will be
logged.
The arguments are:
INTERFACE:
subroutine ESMF_VMAllToAllV(vm, sendData, sendCounts, & sendOffsets, recvData, recvCounts, recvOffsets, syncflag, & commhandle, rc)ARGUMENTS:
type(ESMF_VM), intent(in) :: vm <type>(ESMF_KIND_<kind>), target, intent(in) :: sendData(:) integer, intent(in) :: sendCounts(:) integer, intent(in) :: sendOffsets(:) <type>(ESMF_KIND_<kind>), target, intent(out) :: recvData(:) integer, intent(in) :: recvCounts(:) integer, intent(in) :: recvOffsets(:) -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_Sync_Flag), intent(in), optional :: syncflag type(ESMF_CommHandle), intent(out), optional :: commhandle integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Collective ESMF_VM communication call that performs a total exchange
operation, sending pieces of the contiguous data buffer semdData to
all other PETs while receiving data into the contiguous data buffer
recvData from all other PETs.
This method is overloaded for: ESMF_TYPEKIND_I4,
ESMF_TYPEKIND_R4, ESMF_TYPEKIND_R8, and logical
data types.
TODO: The current version of this method does not provide an
implementation of the non-blocking feature. When calling this
method with syncflag = ESMF_SYNC_NONBLOCKING error code
ESMF_RC_NOT_IMPL will be returned and an error will be
logged.
The arguments are:
INTERFACE:
subroutine ESMF_VMBarrier(vm, rc)ARGUMENTS:
type(ESMF_VM), intent(in) :: vm -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Collective ESMF_VM communication call that blocks calling PET until
all PETs of the VM context have issued the call.
The arguments are:
INTERFACE:
subroutine ESMF_VMBroadcast(vm, bcstData, count, rootPet, & syncflag, commhandle, rc)ARGUMENTS:
type(ESMF_VM), intent(in) :: vm <type>(ESMF_KIND_<kind>), target, intent(inout) :: bcstData(:) integer, intent(in) :: count integer, intent(in) :: rootPet -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_Sync_Flag), intent(in), optional :: syncflag type(ESMF_CommHandle), intent(out), optional :: commhandle integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Collective ESMF_VM communication call that broadcasts a contiguous
data array from rootPet to all other PETs of the ESMF_VM
object.
This method is overloaded for:
ESMF_TYPEKIND_I4,
ESMF_TYPEKIND_R4, ESMF_TYPEKIND_R8,
ESMF_TYPEKIND_LOGICAL,
ESMF_TYPEKIND_CHARACTER.
The arguments are:
INTERFACE:
subroutine ESMF_VMCommWait(vm, commhandle, rc)ARGUMENTS:
type(ESMF_VM), intent(in) :: vm type(ESMF_CommHandle), intent(in) :: commhandle -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Wait for non-blocking VM communication specified by the commhandle to
complete.
The arguments are:
INTERFACE:
subroutine ESMF_VMCommWaitAll(vm, rc)ARGUMENTS:
type(ESMF_VM), intent(in) :: vm -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Wait for all pending non-blocking VM communication within the
specified VM context to complete.
The arguments are:
INTERFACE:
subroutine ESMF_VMGather(vm, sendData, recvData, count, rootPet, & syncflag, commhandle, rc)ARGUMENTS:
type(ESMF_VM), intent(in) :: vm <type>(ESMF_KIND_<kind>), target, intent(in) :: sendData(:) <type>(ESMF_KIND_<kind>), target, intent(out) :: recvData(:) integer, intent(in) :: count integer, intent(in) :: rootPet -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_Sync_Flag), intent(in), optional :: syncflag type(ESMF_CommHandle), intent(out), optional :: commhandle integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Collective ESMF_VM communication call that gathers contiguous data
from all PETs of an ESMF_VM object (including rootPet) into an
array on rootPet.
This method is overloaded for:
ESMF_TYPEKIND_I4,
ESMF_TYPEKIND_R4, ESMF_TYPEKIND_R8,
ESMF_TYPEKIND_LOGICAL.
The arguments are:
INTERFACE:
subroutine ESMF_VMGatherV(vm, sendData, sendCount, recvData, & recvCounts, recvOffsets, rootPet, rc)ARGUMENTS:
type(ESMF_VM), intent(in) :: vm <type>(ESMF_KIND_<kind>), target, intent(in) :: sendData(:) integer, intent(in) :: sendCount <type>(ESMF_KIND_<kind>), target, intent(out) :: recvData(:) integer, intent(in) :: recvCounts(:) integer, intent(in) :: recvOffsets(:) integer, intent(in) :: rootPet -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Collective ESMF_VM communication call that gathers contiguous data
from all PETs of an ESMF_VM object into an array on rootPet.
This method is overloaded for: ESMF_TYPEKIND_I4,
ESMF_TYPEKIND_R4, ESMF_TYPEKIND_R8.
TODO: The current version of this method does not provide an
implementation of the non-blocking feature. When calling this
method with syncflag = ESMF_SYNC_NONBLOCKING error code
ESMF_RC_NOT_IMPL will be returned and an error will be
logged.
The arguments are:
INTERFACE:
! Private name; call using ESMF_VMGet() subroutine ESMF_VMGetDefault(vm, localPet, petCount, & peCount, mpiCommunicator, pthreadsEnabledFlag, openMPEnabledFlag, rc)ARGUMENTS:
type(ESMF_VM), intent(in) :: vm -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: localPet integer, intent(out), optional :: petCount integer, intent(out), optional :: peCount integer, intent(out), optional :: mpiCommunicator logical, intent(out), optional :: pthreadsEnabledFlag logical, intent(out), optional :: openMPEnabledFlag integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Get internal information about the specified ESMF_VM object.
The arguments are:
INTERFACE:
! Private name; call using ESMF_VMGet() subroutine ESMF_VMGetPetLocalInfo(vm, pet, peCount, ssiId, & threadCount, threadId, vas, rc)ARGUMENTS:
type(ESMF_VM), intent(in) :: vm integer, intent(in) :: pet -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: peCount integer, intent(out), optional :: ssiId integer, intent(out), optional :: threadCount integer, intent(out), optional :: threadId integer, intent(out), optional :: vas integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Get internal information about a specific PET within an ESMF_VM
object.
The arguments are:
INTERFACE:
subroutine ESMF_VMGetGlobal(vm, rc)ARGUMENTS:
type(ESMF_VM), intent(out) :: vm -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Get the global ESMF_VM object. This is the VM object that is created during ESMF_Initialize() and is the ultimate parent of all VM objects in an ESMF application. It is identical to the VM object returned by ESMF_Initialize(..., vm=vm, ...).
The ESMF_VMGetGlobal() call provides access to information about the global execution context via the global VM. This call is necessary because ESMF does not created a global ESMF Component during ESMF_Initialize() that could be queried for information about the global execution context of an ESMF application.
Usage of ESMF_VMGetGlobal() from within Component code is
strongly discouraged. ESMF Components should only access their own VM
objects through Component methods. Global information, if required by
the Component user code, should be passed down to the Component from the
driver through the Component calling interface.
The arguments are:
INTERFACE:
subroutine ESMF_VMGetCurrent(vm, rc)ARGUMENTS:
type(ESMF_VM), intent(out) :: vm -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Get the ESMF_VM object of the current execution context. Calling ESMF_VMGetCurrent() within an ESMF Component, will return the same VM object as ESMF_GridCompGet(..., vm=vm, ...) or ESMF_CplCompGet(..., vm=vm, ...).
The main purpose of providing ESMF_VMGetCurrent() is to simplify ESMF adoption in legacy code. Specifically, code that uses MPI_COMM_WORLD deep within its calling tree can easily be modified to use the correct MPI communicator of the current ESMF execution context. The advantage is that these modifications are very local, and do not require wide reaching interface changes in the legacy code to pass down the ESMF component object, or the MPI communicator.
The use of ESMF_VMGetCurrent() is strongly discouraged in newly written Component code. Instead, the ESMF Component object should be used as the appropriate container of ESMF context information. This object should be passed between the subroutines of a Component, and be queried for any Component specific information.
Outside of a Component context, i.e. within the driver context, the call
to ESMF_VMGetCurrent() is identical to ESMF_VMGetGlobal().
The arguments are:
INTERFACE:
subroutine ESMF_VMPrint(vm, rc)ARGUMENTS:
type(ESMF_VM), intent(in) :: vm -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Print internal information about the specified ESMF_VM to
stdout.
The arguments are:
INTERFACE:
subroutine ESMF_VMRecv(vm, recvData, count, srcPet, & syncflag, commhandle, rc)ARGUMENTS:
type(ESMF_VM), intent(in) :: vm integer(ESMF_KIND_I4), target, intent(out) :: recvData(:) integer, intent(in) :: count integer, intent(in) :: srcPet -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_Sync_Flag), intent(in), optional :: syncflag type(ESMF_CommHandle), intent(out), optional :: commhandle integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Receive contiguous data from srcPet within the same ESMF_VM
object.
This method is overloaded for:
ESMF_TYPEKIND_I4,
ESMF_TYPEKIND_R4, ESMF_TYPEKIND_R8,
ESMF_TYPEKIND_LOGICAL,
ESMF_TYPEKIND_CHARACTER.
The arguments are:
INTERFACE:
subroutine ESMF_VMReduce(vm, sendData, recvData, count, & reduceflag, rootPet, syncflag, commhandle, rc)ARGUMENTS:
type(ESMF_VM), intent(in) :: vm <type>(ESMF_KIND_<kind>), target, intent(in) :: sendData(:) <type>(ESMF_KIND_<kind>), target, intent(out) :: recvData(:) integer, intent(in) :: count type(ESMF_Reduce_Flag), intent(in) :: reduceflag integer, intent(in) :: rootPet -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_Sync_Flag), intent(in), optional :: syncflag type(ESMF_CommHandle), intent(out), optional :: commhandle integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Collective ESMF_VM communication call that reduces a contiguous data
array across the ESMF_VM object into a contiguous data array of
the same <type><kind>. The result array is returned on rootPet.
Different reduction operations can be specified.
This method is overloaded for: ESMF_TYPEKIND_I4,
ESMF_TYPEKIND_R4, ESMF_TYPEKIND_R8.
TODO: The current version of this method does not provide an
implementation of the non-blocking feature. When calling this
method with syncflag = ESMF_SYNC_NONBLOCKING error code
ESMF_RC_NOT_IMPL will be returned and an error will be
logged.
The arguments are:
INTERFACE:
subroutine ESMF_VMScatter(vm, sendData, recvData, count, & rootPet, syncflag, commhandle, rc)ARGUMENTS:
type(ESMF_VM), intent(in) :: vm <type>(ESMF_KIND_<kind>), target, intent(in) :: sendData(:) <type>(ESMF_KIND_<kind>), target, intent(out) :: recvData(:) integer, intent(in) :: count integer, intent(in) :: rootPet -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_Sync_Flag), intent(in), optional :: syncflag type(ESMF_CommHandle), intent(out), optional :: commhandle integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Collective ESMF_VM communication call that scatters contiguous data
from the rootPet to all PETs across the ESMF_VM object
(including rootPet).
This method is overloaded for:
ESMF_TYPEKIND_I4,
ESMF_TYPEKIND_R4, ESMF_TYPEKIND_R8,
ESMF_TYPEKIND_LOGICAL.
The arguments are:
INTERFACE:
subroutine ESMF_VMScatterV(vm, sendData, sendCounts, & sendOffsets, recvData, recvCount, rootPet, rc)ARGUMENTS:
type(ESMF_VM), intent(in) :: vm <type>(ESMF_KIND_<kind>), target, intent(in) :: sendData(:) integer, intent(in) :: sendCounts(:) integer, intent(in) :: sendOffsets(:) <type>(ESMF_KIND_<kind>), target, intent(out) :: recvData(:) integer, intent(in) :: recvCount integer, intent(in) :: rootPet -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Collective ESMF_VM communication call that scatters contiguous data
from the rootPet to all PETs across the ESMF_VM object
(including rootPet).
This method is overloaded for: ESMF_TYPEKIND_I4,
ESMF_TYPEKIND_R4, ESMF_TYPEKIND_R8.
The arguments are:
INTERFACE:
subroutine ESMF_VMSend(vm, sendData, count, dstPet, & syncflag, commhandle, rc)ARGUMENTS:
type(ESMF_VM), intent(in) :: vm <type>(ESMF_KIND_<kind>), target, intent(in) :: sendData(:) integer, intent(in) :: count integer, intent(in) :: dstPet -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_Sync_Flag), intent(in), optional :: syncflag type(ESMF_CommHandle), intent(out), optional :: commhandle integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Send contiguous data to dstPet within the same ESMF_VM object.
The arguments are:
INTERFACE:
subroutine ESMF_VMSendRecv(vm, sendData, sendCount, dstPet, & recvData, recvCount, srcPet, syncflag, commhandle, rc)ARGUMENTS:
type(ESMF_VM), intent(in) :: vm <type>(ESMF_KIND_<kind>), target, intent(in) :: sendData(:) integer, intent(in) :: sendCount integer, intent(in) :: dstPet <type>(ESMF_KIND_<kind>), target, intent(out) :: recvData(:) integer, intent(in) :: recvCount integer, intent(in) :: srcPet -- The following arguments require argument keyword syntax (e.g. rc=rc). -- type(ESMF_Sync_Flag), intent(in), optional :: syncflag type(ESMF_CommHandle), intent(out), optional :: commhandle integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Send contiguous data to dstPet within the same ESMF_VM object
while receiving contiguous data from srcPet within the same
ESMF_VM object. The sendData and recvData arrays must be
disjoint!
This method is overloaded for:
ESMF_TYPEKIND_I4,
ESMF_TYPEKIND_R4, ESMF_TYPEKIND_R8,
ESMF_TYPEKIND_LOGICAL,
ESMF_TYPEKIND_CHARACTER.
The arguments are:
INTERFACE:
subroutine ESMF_VMValidate(vm, rc)ARGUMENTS:
type(ESMF_VM), intent(in) :: vm -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Validates that the vm is internally consistent. The method returns an error code if problems are found.
The arguments are:
INTERFACE:
subroutine ESMF_VMWtime(time, rc)ARGUMENTS:
real(ESMF_KIND_R8), intent(out) :: time -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Get floating-point number of seconds of elapsed wall-clock time since some
time in the past.
The arguments are:
INTERFACE:
subroutine ESMF_VMWtimeDelay(delay, rc)ARGUMENTS:
real(ESMF_KIND_R8), intent(in) :: delay -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Delay execution for amount of seconds.
The arguments are:
INTERFACE:
subroutine ESMF_VMWtimePrec(prec, rc)ARGUMENTS:
real(ESMF_KIND_R8), intent(out) :: prec -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Get a run-time estimate of the timer precision as floating-point number
of seconds. This is a relatively expensive call since the timer precision
is measured several times before the maximum is returned as the estimate.
The returned value is PET-specific and may differ across the VM
context.
The arguments are:
The ESMF Fortran I/O utilities provide portable methods to access capabilities which are often implemented in different ways amongst different environments. Currently, two utility methods are implemented: ESMF_IOUnitGet(), to find an unopened unit number within the range of unit numbers that ESMF is allowed to use, and ESMF_IOUnitFlush() to flush the I/O buffer associated with a specific Fortran unit.
call ESMF_UtilIOUnitGet (unit=grid_unit, rc=rc) open (unit=grid_unit, file='grid_data.dat', status='old', action='read')
By default, unit numbers between 50 and 99 are scanned to find an unopened unit number.
Internally, ESMF also uses ESMF_UtilIOUnitGet() when it needs to open Fortran unit numbers for file I/O. By using the same API for both user and ESMF code, unit number collisions can be avoided.
When integrating ESMF into an application where there are conflicts with other uses of the same unit number range, such as when hard-coded unit number values are used, an alternative unit number range can be specified. The ESMF_Initialize() optional arguments IOUnitLower and IOUnitUpper may be set as needed. Note that IOUnitUpper must be set to a value higher than IOUnitLower, and that both must be non-negative. Otherwise ESMF_Initialize will return a return code of ESMF_FAILURE. ESMF itself does not typically need more than about five units for internal use.
call ESMF_Initialize (..., IOUnitLower=120, IOUnitUpper=140)
All current Fortran environments have preconnected unit numbers, such as units 5 and 6 for standard input and output, in the single digit range. So it is recommended that the unit number range is chosen to begin at unit 10 or higher to avoid these preconnected units.
Fortran run-time libraries generally use buffering techniques to improve I/O performance. However output buffering can be problematic when output is needed, but is ``trapped'' in the buffer because it is not full. This is a common occurance when debugging a program, and inserting WRITE statements to track down the bad area of code. If the program crashes before the output buffer has been flushed, the desired debugging output may never be seen -- giving a misleading indication of where the problem occurred. It would be desirable to ensure that the output buffer is flushed at predictable points in the program in order to get the needed results. Likewise, in parallel code, predictable flushing of output buffers is a common requirement, often in conjunction with ESMF_VMBarrier() calls.
The ESMF_UtilIOUnitFlush() API is provided to flush a unit as desired. Here is an example of code which prints debug values, and serializes the output to a terminal in PET order:
type(ESMF_VM) :: vm integer :: tty_unit integer :: me, npets call ESMF_Initialize (vm=vm, rc=rc) call ESMF_VMGet (vm, localPet=me, petCount=npes) call ESMF_UtilIOUnitGet (unit=tty_unit) open (unit=tty_unit, file='/dev/tty', status='old', action='write') ... call ESMF_VMBarrier (vm=vm) do, i=0, npets-1 if (i == me) then write (tty_unit, *) 'PET: ', i, ', values are: ', a, b, c call ESMF_UtilIOUnitFlush (unit=tty_unit) end if call ESMF_VMBarrier (vm=vm) end do
When ESMF needs to open a Fortran I/O unit, it calls ESMF_IOUnitGet() to find an unopened unit number. As delivered, the range of unit numbers that are searched are between ESMF_LOG_FORTRAN_UNIT_NUMBER (normally set to 50), and ESMF_LOG_UPPER (normally set to 99.) Unopened unit numbers are found by using the Fortran INQUIRE statement.
When integrating ESMF into an application where there are conflicts with other uses of the same unit number range, an alternative range can be specified in the ESMF_Initialize() call by setting the IOUnitLower and IOUnitUpper arguments as needed. ESMF_IOUnitGet() will then search the alternate range of unit numbers. Note that IOUnitUpper must be set to a value higher than IOUnitLower, and that both must be non-negative. Otherwise ESMF_Initialize will return a return code of ESMF_FAILURE.
Fortran unit numbers are not standardized in the Fortran 90 Standard. The standard only requires that they be non-negative integers. But other than that, it is up to the compiler writers and application developers to provide and use units which work with the particular implementation. For example, units 5 and 6 are a defacto standard for ``standard input'' and ``standard output'' -- even though this is not specified in the actual Fortran standard. The Fortran standard also does not specifiy which unit numbers can be used, nor does it specify how many can be open simultaneously.
Since all current compilers have preconnected unit numbers, and these are typically found on units lower than 10, it is recommended that applications use unit numbers 10 and higher.
When ESMF needs to flush a Fortran unit, the ESMF_IOUnitFlush() API is used to centralize the file flushing capability, because Fortran has not historically had a standard mechanism for flushing output buffers. Most compilers run-time libraries support various library extensions to provide this functionality -- though, being non-standard, the spelling and number of arguments vary between implementations. Fortran 2003 also provides for a FLUSH statement which is built into the language. When possible, ESMF_IOUnitFlush() uses the F2003 FLUSH statement. With older compilers, the appropriate library call is made.
INTERFACE:
subroutine ESMF_UtilGetArg(argindex, argvalue, arglength, rc)ARGUMENTS:
integer, intent(in) :: argindex -- The following arguments require argument keyword syntax (e.g. rc=rc). -- character(*), intent(out), optional :: argvalue integer, intent(out), optional :: arglength integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
This method returns a copy of a command line argument specified when the process was started. This argument is the same as an equivalent C++ program would find in the argv array.
Some MPI implementations do not consistently provide command line arguments on PETs other than PET 0. It is therefore recommended that PET 0 call this method and broadcast the results to the other PETs by using the ESMF_VMBroadcast() method.
The arguments are:
INTERFACE:
subroutine ESMF_UtilGetArgC(count, rc)ARGUMENTS:
integer, intent(out) :: count -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
This method returns the number of command line arguments specified when the process was started.
The number of arguments returned does not include the name of the command itself - which is typically returned as argument zero.
Some MPI implementations do not consistently provide command line arguments on PETs other than PET 0. It is therefore recommended that PET 0 call this method and broadcast the results to the other PETs by using the ESMF_VMBroadcast() method.
The arguments are:
INTERFACE:
subroutine ESMF_UtilGetArgIndex(argvalue, argindex, rc)ARGUMENTS:
character(*), intent(in) :: argvalue -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: argindex integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
This method searches for, and returns the index of a desired command line argument. An example might be to find a specific keyword (e.g., -esmf_path) so that its associated value argument could be obtained by adding 1 to the argindex and calling ESMF_UtilGetArg().
Some MPI implementations do not consistently provide command line arguments on PETs other than PET 0. It is therefore recommended that PET 0 call this method and broadcast the results to the other PETs by using the ESMF_VMBroadcast() method.
The arguments are:
INTERFACE:
subroutine ESMF_UtilIOUnitFlush(unit, rc)PARAMETERS:
integer, intent(in) :: unit -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Call the system-dependent routine to force output on a specific Fortran unit number.
The arguments are:
INTERFACE:
subroutine ESMF_UtilIOUnitGet(unit, rc)ARGUMENTS:
integer, intent(out) :: unit -- The following arguments require argument keyword syntax (e.g. rc=rc). -- integer, intent(out), optional :: rcSTATUS:
DESCRIPTION:
Scan for, and return, a free Fortran I/O unit number. By default, the range of unit numbers returned is between 50 and 99 (parameters ESMF_LOG_FORTRAN_UNIT_NUMBER and ESMF_LOG_UPPER respectively.) When integrating ESMF into an application where these values conflict with other usages, the range of values may be moved by setting the optional IOUnitLower and IOUnitUpper arguments in the initial ESMF_Initialize() call with values in a safe, alternate, range.
The Fortran unit number which is returned is not reserved in any way. Successive calls without intervening OPEN or CLOSE statements (or other means of connecting to units), might not return a unique unit number. It is recommended that an OPEN statement immediately follow the call to ESMF_IOUnitGet() to activate the unit.
The arguments are: