next up previous contents
Next: Bibliography Up: ESMF_refdoc Previous: 3 Infrastructure: Fields and   Contents

Subsections

4 Infrastructure: Utilities

30 Overview of Infrastructure Utility Classes

The ESMF utilities are a set of tools for quickly assembling modeling applications. The Time Management Library provides utilities for time and date representation and calculation, and higher-level utilities that control model time stepping and alarming.

The Array class offers an efficient, language-neutral way of storing and manipulating data arrays.

The Communications/Memory/Kernel library provides utilities for isolating system-dependent functions to ease platform portability. It provides services to represent a particular machine's characteristics and to organize these into processor lists and layouts to allow for optimal allocation of resources to an ESMF component. Also provided is a unified interface for system-dependent communication services such as MPI or pthreads.

ESMF Configuration Management is based on NASA DAO's Inpak package, a collection of routines for accessing files containing input parameters stored in an ASCII format.

31 Attribute Class

31.1 Description

The Attribute class is used to hold the metadata for other ESMF objects. This class can be used to build Attribute hierarchies which connect the Attributes of different ESMF classes. The class is also capable of allowing the representation of standard Attribute packages for a more unified description of an object. All Attributes are consistent across the entire virtual machine of the object to which they are attached. This class is only partially implemented in this release.

31.1.1 Attribute Representation in ESMF

Attributes are meant to be used as a tool for the user to help internally document their project. Several ESMF objects are allowed to have Attributes associated with them, these objects are the following:

Each Attribute contains a name-value pair in which the value can be any of several numeric, character, and logical types. See Figure 25 for the available Attribute value types. All Attributes also contain character strings specifying the convention, purpose, and object type of the Attribute for identification purposes - each of which is initialized as an empty string until specified otherwise. Each Attribute can be uniquely identified by its name, convention, purpose within any one ESMF object.

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.

31.1.2 Attribute Hierarchies

Of the ESMF objects with Attributes, only some can link their Attributes together in an Attribute hierarchy. These objects are:

The most common use for this 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. In addition, the State will automatically set the import and export boolean valued Attributes that are part of the ESMF supplied standard Attribute package for Field when that Field is added to the State.

Attribute hierarchies are linked in a ``shallow" manner, meaning that the Attributes belonging to an external object are not copied, they are merely referenced by a pointer. This is important to ensure that the Attribute hierarchy has a one-to-one correspondence with the object hierarchy.


31.1.3 Attribute Packages

At this time, all ESMF objects which are enabled to contain Attributes can also contain Attribute packages. Every Attribute package is specified by a convention and a purpose, hereafter called specifiers, such as ``CF" (see below) and ``general". These specifiers are used to validate ESMF Attribute packages against existing metadata conventions. One can use an ESMF supplied standard Attribute package, specify their own Attribute packages, or add customized Attributes to the ESMF supplied Attribute packages. Currently, working with Attribute packages is quite involved, but future development with IO will allow for a more automated approach to populating Attribute packages from a file.

The standard Attribute packages supplied by ESMF exist for the following ESMF objects:

The ESMF standard Attribute packages are based on a blend of the Climate and Forecast (CF) and Earth System Grid (ESG) conventions. When additional Attributes beyond the ESMF supplied Attribute packages are desired, these can be generated with the Attribute package nesting capabilities. User supplied Attribute packages will also be an option in future releases. An example of some more standardized user supplied Attribute packages are in Tables 31.1.3 - 31.1.3, which summarize the Attribute packages available at this point in time.




Component Attribute Packages
Convention Purpose Name
ESMF General Component ESG General +
ESG General Component CF General +
     
    Agency
    Author
    CodingLanguage
    Discipline
    FullName
    Institution
    ModelComponentFramework
    Name
    PhysicalDomain
    Version
CF General Comment
    References




State Attribute Packages
Convention Purpose Name
ESMF General Export
    Import




Field Attribute Packages
Convention Purpose Name
ESMF General Field ESG General +
ESG General Field CF Extended +
     
    Export
    Import
CF Extended Field CF General +
     
    StandardName
CF General LongName
    Name
    Units

Array Attribute Packages
Convention Purpose Name
ESMF General Array ESG General +
ESG General Array CF Extended +
     
    Export
    Import
CF Extended Array CF General +
     
    StandardName
CF General LongName
    Name
    Units

Grid Attribute Packages
Convention Purpose Name
ESMF General Grid GridSpec General +
GridSpec General CongruentTiles
    GridType
    DimOrder
    DiscretizationType
    GeometryType
    IsConformal
    IsPoleCovered
    IsRegular
    IsUniform
    NorthPoleLocation
    NumberOfCells
    NumDims
    NX
    NY
    NZ
    Resolution







ESMF also allows nesting of Attribute packages. This capability is intended to help organize different metadata compliance levels, such as CF and ESG. The nesting of Attribute packages is also very helpful when adding customized Attributes to a package. The main use of the nesting capabilities of Attribute packages is geared towards organizing different metadata compliance levels. For instance, the CF metadata standard for Fields requires that there be Attributes to track the name, long_name, standard_name, and units of the Field. The ESG standard, on the other hand, requires two additional Attributes called import and export. In this case the ESMF representation of the ESG compliant Attribute package for a Field would involve a nested Attribute package structure. This would involve the ESG-specific Attribute package, containing the Attributes import and export containing a nested version of the CF-specific Attribute package, with the Attributes name, long_name, standard_name, and units. An Attribute package can be nested by including the specifiers of both packages in the ESMF_AttributeAdd() interface call.

The nesting capabilities of Attribute packages are also very useful for organizing the customized metadata supplied by a user. For example, if a user was not satisfied with the metadata support required in the ESG convention for Field they could supply a list of Attributes they would like to support. This new Attribute package would then be used as an additional layer, inside which the Attribute package of ESG would be nested, inside which the CF Attribute package would be nested. One important thing to remember when working with nested Attribute packages is that naming two Attributes the same in the same nested structure can yield undefined behavior.

An explanation of the specifiers 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.

31.2 Object Model

Each Attribute contains a name-value pair in which the value can be any of several numeric, character, and logical types. The allowable ESMF Attribute value types include:

The other members of the Attribute class can be seen in Figure 25 which shows a UML representation of the ESMF Attribute object. For a more detailed view of how Attribute packages and hierarchies are formed, see Figures 26 and 27, respectively.

Figure 25: The structure of the Attribute class
\includegraphics[width=4in,height=6.5in]{AttributeClassUML}

Figure 26: The internal object organization for the representation of Attribute packages
\includegraphics[width=5.5in,height=6in]{AttributePackageUML}

Figure 27: The internal object organization for the representation of Attribute hierarchies
\includegraphics[width=5.5in,height=6in]{AttributeHierarchyUML}

31.3 Use and Examples

This section describes the use of the Attribute class. There are seven 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 last four examples cover setting of Attribute packages and custom Attributes from an XML file.


31.3.1 Example: Basic Attribute usage

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, 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_Mod
      implicit none

      ! Local variables  
      integer                 :: rc, finalrc, petCount, localPet, &
                                 itemCount, count
      type(ESMF_VM)           :: vm
      type(ESMF_GridComp)     :: gridcomp
      character(ESMF_MAXSTR)  :: name

      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
      
      type(ESMF_TypeKind)   :: tk

      ! initialize ESMF
      finalrc = ESMF_SUCCESS
      call ESMF_Initialize(vm=vm, rc=rc)
      
      ! get the vm
      call ESMF_VMGet(vm, petCount=petCount, localPet=localPet, rc=rc)
      if (rc/=ESMF_SUCCESS) goto 10

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)

31.3.2 Example: Intermediate Attribute usage: Attribute Packages

This example is slightly more complex than the example presented in section 31.3.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. Attributes 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. The first thing we must do is declare variables and initialize ESMF.

      ! Use ESMF framework module
      use ESMF_Mod
      implicit none

      ! Local variables  
      integer                 :: rc, finalrc, petCount, localPet
      type(ESMF_VM)           :: vm
      type(ESMF_Field)        :: DPEDT,DTDT,DUDT,DVDT,PHIS,QTR,CNV,CONVCPT,&
                                 CONVKE,CONVPHI
      type(ESMF_FieldBundle)  :: fbundle
      type(ESMF_State)        :: importState, exportState
      type(ESMF_GridComp)     :: gridcomp
      character(ESMF_MAXSTR)  :: name1,name2,name3,name4, &
                                 value1,value2,value3, value4, &
                                 convESMF,convCC,purpGen
      
      character(ESMF_MAXSTR),dimension(2)   :: attrList         

      ! initialize ESMF
      finalrc = ESMF_SUCCESS
      call ESMF_Initialize(vm=vm, rc=rc)
      
      ! get the vm
      call ESMF_VMGet(vm, petCount=petCount, localPet=localPet, rc=rc)
      if (rc/=ESMF_SUCCESS) goto 10

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_component", &
          petList=(/0/), rc=rc)
      else 
        gridcomp = ESMF_GridCompCreate(name="gridded_component", &
          petList=(/0,1,2,3/), rc=rc)
      endif
      importState = ESMF_StateCreate("importState", ESMF_STATE_IMPORT, rc=rc)
      exportState = ESMF_StateCreate("exportState", ESMF_STATE_EXPORT, rc=rc)
        
      DPEDT = ESMF_FieldCreateEmpty(name='DPEDT', rc=rc)
      DTDT = ESMF_FieldCreateEmpty(name='DTDT', rc=rc)
      DUDT = ESMF_FieldCreateEmpty(name='DUDT', rc=rc)
      DVDT = ESMF_FieldCreateEmpty(name='DVDT', rc=rc)
      PHIS = ESMF_FieldCreateEmpty(name='PHIS', rc=rc)
      QTR = ESMF_FieldCreateEmpty(name='QTR', rc=rc)
      CNV = ESMF_FieldCreateEmpty(name='CNV', rc=rc)
      CONVCPT = ESMF_FieldCreateEmpty(name='CONVCPT', rc=rc)
      CONVKE = ESMF_FieldCreateEmpty(name='CONVKE', rc=rc)
      CONVPHI = ESMF_FieldCreateEmpty(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)

      ! DTDT
      call ESMF_AttributeAdd(DTDT, convention=convESMF, purpose=purpGen, rc=rc)
      call ESMF_AttributeAdd(DTDT, convention=convCC, purpose=purpGen, &
        attrList=attrList, nestConvention=convESMF, nestPurpose=purpGen, rc=rc)

      ! DUDT
      call ESMF_AttributeAdd(DUDT, convention=convESMF, purpose=purpGen, rc=rc)
      call ESMF_AttributeAdd(DUDT, convention=convCC, purpose=purpGen, &
        attrList=attrList, nestConvention=convESMF, nestPurpose=purpGen, rc=rc)

      ! DVDT
      call ESMF_AttributeAdd(DVDT, convention=convESMF, purpose=purpGen, rc=rc)
      call ESMF_AttributeAdd(DVDT, convention=convCC, purpose=purpGen, &
        attrList=attrList, nestConvention=convESMF, nestPurpose=purpGen, rc=rc)

      ! PHIS
      call ESMF_AttributeAdd(PHIS, convention=convESMF, purpose=purpGen, rc=rc)
      call ESMF_AttributeAdd(PHIS, convention=convCC, purpose=purpGen, &
        attrList=attrList, nestConvention=convESMF, nestPurpose=purpGen, rc=rc)

      ! QTR
      call ESMF_AttributeAdd(QTR, convention=convESMF, purpose=purpGen, rc=rc)
      call ESMF_AttributeAdd(QTR, convention=convCC, purpose=purpGen, &
        attrList=attrList, nestConvention=convESMF, nestPurpose=purpGen, rc=rc)

      ! CNV
      call ESMF_AttributeAdd(CNV, convention=convESMF, purpose=purpGen, rc=rc)
      call ESMF_AttributeAdd(CNV, convention=convCC, purpose=purpGen, &
        attrList=attrList, nestConvention=convESMF, nestPurpose=purpGen, rc=rc)

      ! CONVCPT
      call ESMF_AttributeAdd(CONVCPT, convention=convESMF, purpose=purpGen, rc=rc)
      call ESMF_AttributeAdd(CONVCPT, convention=convCC, purpose=purpGen, &
        attrList=attrList, nestConvention=convESMF, nestPurpose=purpGen, rc=rc)

      ! CONVKE
      call ESMF_AttributeAdd(CONVKE, convention=convESMF, purpose=purpGen, rc=rc)
      call ESMF_AttributeAdd(CONVKE, convention=convCC, purpose=purpGen, &
        attrList=attrList, nestConvention=convESMF, nestPurpose=purpGen, rc=rc)

      ! CONVPHI
      call ESMF_AttributeAdd(CONVPHI, convention=convESMF, purpose=purpGen, rc=rc)
      call ESMF_AttributeAdd(CONVPHI, convention=convCC, purpose=purpGen, &
        attrList=attrList, nestConvention=convESMF, nestPurpose=purpGen, rc=rc)
      
      call ESMF_AttributeAdd(gridcomp, convention=convESMF, &
        purpose=purpGen, rc=rc)

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 = 'Name'
      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)
    
      ! DTDT
      value1 = 'DTDT'
      value2 = 'tendency_of_air_temperature'
      value3 = 'Delta-p weighted temperature tendency'
      value4 = 'Pa K s-1'
      ! Custom Attributes
      call ESMF_AttributeSet(DTDT, name='Coordinates', value='latlon', &
        convention=convCC, purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(DTDT, name='Mask', value='yes', &
        convention=convCC, purpose=purpGen, rc=rc)
      ! ESMF Attributes
      call ESMF_AttributeSet(DTDT, name1, value1, convention=convESMF, &
        purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(DTDT, name2, value2, convention=convESMF, &
        purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(DTDT, name3, value3, convention=convESMF, &
        purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(DTDT, name4, value4, convention=convESMF, &
        purpose=purpGen, rc=rc)
    
      ! DUDT
      value1 = 'DUDT'
      value2 = 'tendency_of_eastward_wind'
      value3 = 'Eastward wind tendency'
      value4 = 'm s-2'
      ! Custom Attributes
      call ESMF_AttributeSet(DUDT, name='Coordinates', value='latlon', &
        convention=convCC, purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(DUDT, name='Mask', value='yes', &
        convention=convCC, purpose=purpGen, rc=rc)
      ! ESMF Attributes
      call ESMF_AttributeSet(DUDT, name1, value1, convention=convESMF, &
        purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(DUDT, name2, value2, convention=convESMF, &
        purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(DUDT, name3, value3, convention=convESMF, &
        purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(DUDT, name4, value4, convention=convESMF, &
        purpose=purpGen, rc=rc)
    
      ! DVDT
      value1 = 'DVDT'
      value2 = 'tendency_of_northward_wind'
      value3 = 'Northward wind tendency'
      value4 = 'm s-2'
      ! Custom Attributes
      call ESMF_AttributeSet(DVDT, name='Coordinates', value='latlon', &
        convention=convCC, purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(DVDT, name='Mask', value='yes', &
        convention=convCC, purpose=purpGen, rc=rc)
      ! ESMF Attributes
      call ESMF_AttributeSet(DVDT, name1, value1, convention=convESMF, &
        purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(DVDT, name2, value2, convention=convESMF, &
        purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(DVDT, name3, value3, convention=convESMF, &
        purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(DVDT, name4, value4, convention=convESMF, &
        purpose=purpGen, rc=rc)
    
      ! PHIS
      value1 = 'PHIS'
      value2 = 'surface_geopotential'
      value3 = 'Surface geopotential height'
      value4 = 'm2 s-2'
      ! Custom Attributes
      call ESMF_AttributeSet(PHIS, name='Coordinates', value='latlon', &
        convention=convCC, purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(PHIS, name='Mask', value='yes', &
        convention=convCC, purpose=purpGen, rc=rc)
      ! ESMF Attributes
      call ESMF_AttributeSet(PHIS, name1, value1, convention=convESMF, &
        purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(PHIS, name2, value2, convention=convESMF, &
        purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(PHIS, name3, value3, convention=convESMF, &
        purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(PHIS, name4, value4, convention=convESMF, &
        purpose=purpGen, rc=rc)
    
      ! QTR
      value1 = 'QTR'
      value2 = ''
      value3 = 'Advected quantities'
      value4 = 'unknown'
      ! Custom Attributes
      call ESMF_AttributeSet(QTR, name='Coordinates', value='latlon', &
        convention=convCC, purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(QTR, name='Mask', value='yes', &
        convention=convCC, purpose=purpGen, rc=rc)
      ! ESMF Attributes
      call ESMF_AttributeSet(QTR, name1, value1, convention=convESMF, &
        purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(QTR, name2, value2, convention=convESMF, &
        purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(QTR, name3, value3, convention=convESMF, &
        purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(QTR, name4, value4, convention=convESMF, &
        purpose=purpGen, rc=rc)
    
      ! CNV
      value1 = 'CNV'
      value2 = 'atmosphere_kinetic_energy_content'
      value3 = 'Generation of atmosphere kinetic energy content'
      value4 = 'W m-2'
      ! Custom Attributes
      call ESMF_AttributeSet(CNV, name='Coordinates', value='latlon', &
        convention=convCC, purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(CNV, name='Mask', value='yes', &
        convention=convCC, purpose=purpGen, rc=rc)
      ! ESMF Attributes
      call ESMF_AttributeSet(CNV, name1, value1, convention=convESMF, &
        purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(CNV, name2, value2, convention=convESMF, &
        purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(CNV, name3, value3, convention=convESMF, &
        purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(CNV, name4, value4, convention=convESMF, &
        purpose=purpGen, rc=rc)
    
      ! CONVCPT
      value1 = 'CONVCPT'
      value2 = ''
      value3 = 'Vertically integrated enthalpy convergence'
      value4 = 'W m-2'
      ! Custom Attributes
      call ESMF_AttributeSet(CONVCPT, name='Coordinates', value='latlon', &
        convention=convCC, purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(CONVCPT, name='Mask', value='yes', &
        convention=convCC, purpose=purpGen, rc=rc)
      ! ESMF Attributes
      call ESMF_AttributeSet(CONVCPT, name1, value1, convention=convESMF, &
        purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(CONVCPT, name2, value2, convention=convESMF, &
        purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(CONVCPT, name3, value3, convention=convESMF, &
        purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(CONVCPT, name4, value4, convention=convESMF, &
        purpose=purpGen, rc=rc)
    
      ! CONVKE
      value1 = 'CONVKE'
      value2 = ''
      value3 = 'Vertically integrated kinetic energy convergence'
      value4 = 'W m-2'
      ! Custom Attributes
      call ESMF_AttributeSet(CONVKE, name='Coordinates', value='latlon', &
        convention=convCC, purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(CONVKE, name='Mask', value='yes', &
        convention=convCC, purpose=purpGen, rc=rc)
      ! ESMF Attributes
      call ESMF_AttributeSet(CONVKE, name1, value1, convention=convESMF, &
        purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(CONVKE, name2, value2, convention=convESMF, &
        purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(CONVKE, name3, value3, convention=convESMF, &
        purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(CONVKE, name4, value4, convention=convESMF, &
        purpose=purpGen, rc=rc)
    
      ! CONVPHI
      value1 = 'CONVPHI'
      value2 = ''
      value3 = 'Vertically integrated geopotential convergence'
      value4 = 'W m-2'
      ! Custom Attributes
      call ESMF_AttributeSet(CONVPHI, name='Coordinates', value='latlon', &
        convention=convCC, purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(CONVPHI, name='Mask', value='yes', &
        convention=convCC, purpose=purpGen, rc=rc)
      ! ESMF Attributes
      call ESMF_AttributeSet(CONVPHI, name1, value1, convention=convESMF, &
        purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(CONVPHI, name2, value2, convention=convESMF, &
        purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(CONVPHI, name3, value3, convention=convESMF, &
        purpose=purpGen, rc=rc)
      call ESMF_AttributeSet(CONVPHI, name4, value4, convention=convESMF, &
        purpose=purpGen, rc=rc)

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, 'FullName', &
      '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, 'Name', '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, fieldbundle=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)

31.3.3 Example: Advanced Attribute usage: Attributes in a Distributed Environment

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.

The first thing we must do is declare variables and initialize ESMF in the application driver.

      integer                 :: rc, finalrc, petCount, localPet
      type(ESMF_VM)           :: vm
      type(ESMF_State)        :: c1exp, c2imp
      type(ESMF_GridComp)     :: gridcomp1
      type(ESMF_GridComp)     :: gridcomp2
      type(ESMF_CplComp)      :: cplcomp
      character(ESMF_MAXSTR)  :: convESMF,purpGen

      finalrc = ESMF_SUCCESS
      call ESMF_Initialize(vm=vm, rc=rc)
      
      call ESMF_VMGet(vm, petCount=petCount, localPet=localPet, rc=rc)
      if (rc/=ESMF_SUCCESS) print *, "ERROR!"

Still 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("Comp1 exportState", &
        ESMF_STATE_EXPORT, rc=rc)
      c2imp = ESMF_StateCreate("Comp2 importState", &
        ESMF_STATE_IMPORT, 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, 'FullName', &
      '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, 'Name', '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, 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)      :: fbundle
    character(ESMF_MAXSTR),dimension(2)   :: attrList         
    
    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

    call ESMF_ArraySpecSet(arrayspec, typekind=ESMF_TYPEKIND_R8, rank=2, rc=rc)
    if (rc/=ESMF_SUCCESS) return
    grid = ESMF_GridCreateShapeTile(minIndex=(/1,1/), maxIndex=(/100,150/), &
      regDecomp=(/1,petCount/), &
      gridEdgeLWidth=(/0,0/), gridEdgeUWidth=(/0,0/), &
      indexflag=ESMF_INDEX_GLOBAL, rc=rc)
    if (rc/=ESMF_SUCCESS) return

This first bit is a verification that the ESMF_StateReconcile() call will correctly reconcile Attributes and Attribute packages that are attached to the top level State in an Attribute hierarchy. During the initialize phase of the coupler Component, the structure of these Attributes should be reconciled across the VM. The value of the Attributes in this structure are not guaranteed after the completion of ESMF_StateReconcile(), as that is the responsibility of the ESMF_AttributeUpdate() call. There will be more on this subject when we get to the coupler Component.

    call ESMF_AttributeSet(exportState, name="TESTESTEST", &
                           value="SUCCESUCCESUCCES", rc=status)
    if (status .ne. ESMF_SUCCESS) return

At this point the Fields will need to have Attribute packages attached to them, and the Attributes will be set with appropriate values. This process is quite involved at present, but will be more streamlined with the addition of the ESMF I/O class.

    convCC = 'CustomConvention'
    convESMF = 'ESMF'
    purpGen = 'General'
    name1 = 'Name'
    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)
    if (status .ne. ESMF_SUCCESS) return

    value1 = 'DTDT'
    value2 = 'tendency_of_air_temperature'
    value3 = 'Delta-p weighted temperature tendency'
    value4 = 'Pa K s-1'

    DTDT = ESMF_FieldCreate(grid, arrayspec=arrayspec, &
              staggerloc=ESMF_STAGGERLOC_CENTER, rc=status)
    call ESMF_AttributeAdd(DTDT, convention=convESMF, purpose=purpGen, &
      rc=status)
    call ESMF_AttributeSet(DTDT, name1, value1, convention=convESMF, &
      purpose=purpGen, rc=status)
    call ESMF_AttributeSet(DTDT, name2, value2, convention=convESMF, &
      purpose=purpGen, rc=status)
    call ESMF_AttributeSet(DTDT, name3, value3, convention=convESMF, &
      purpose=purpGen, rc=status)
    call ESMF_AttributeSet(DTDT, name4, value4, convention=convESMF, &
      purpose=purpGen, rc=status)
    if (status .ne. ESMF_SUCCESS) return

    value1 = 'DUDT'
    value2 = 'tendency_of_eastward_wind'
    value3 = 'Eastward wind tendency'
    value4 = 'm s-2'
      
    DUDT = ESMF_FieldCreate(grid, arrayspec=arrayspec, &
              staggerloc=ESMF_STAGGERLOC_CENTER, rc=status)
    call ESMF_AttributeAdd(DUDT, convention=convESMF, purpose=purpGen, &
      rc=status)
    call ESMF_AttributeSet(DUDT, name1, value1, convention=convESMF, &
      purpose=purpGen, rc=status)
    call ESMF_AttributeSet(DUDT, name2, value2, convention=convESMF, &
      purpose=purpGen, rc=status)
    call ESMF_AttributeSet(DUDT, name3, value3, convention=convESMF, &
      purpose=purpGen, rc=status)
    call ESMF_AttributeSet(DUDT, name4, value4, convention=convESMF, &
      purpose=purpGen, rc=status)
    if (status .ne. ESMF_SUCCESS) return
    
    value1 = 'DVDT'
    value2 = 'tendency_of_northward_wind'
    value3 = 'Northward wind tendency'
    value4 = 'm s-2'
      
    DVDT = ESMF_FieldCreate(grid, arrayspec=arrayspec, &
              staggerloc=ESMF_STAGGERLOC_CENTER, rc=status)
    call ESMF_AttributeAdd(DVDT, convention=convESMF, purpose=purpGen, &
      rc=status)
    call ESMF_AttributeSet(DVDT, name1, value1, convention=convESMF, &
      purpose=purpGen, rc=status)
    call ESMF_AttributeSet(DVDT, name2, value2, convention=convESMF, &
      purpose=purpGen, rc=status)
    call ESMF_AttributeSet(DVDT, name3, value3, convention=convESMF, &
      purpose=purpGen, rc=status)
    call ESMF_AttributeSet(DVDT, name4, value4, convention=convESMF, &
      purpose=purpGen, rc=status)
    if (status .ne. ESMF_SUCCESS) return

    value1 = 'PHIS'
    value2 = 'surface_geopotential'
    value3 = 'Surface geopotential height'
    value4 = 'm2 s-2'
      
    PHIS = ESMF_FieldCreate(grid, arrayspec=arrayspec, &
              staggerloc=ESMF_STAGGERLOC_CENTER, rc=status)
    call ESMF_AttributeAdd(PHIS, convention=convESMF, purpose=purpGen, &
      rc=status)
    call ESMF_AttributeSet(PHIS, name1, value1, convention=convESMF, &
      purpose=purpGen, rc=status)
    call ESMF_AttributeSet(PHIS, name2, value2, convention=convESMF, &
      purpose=purpGen, rc=status)
    call ESMF_AttributeSet(PHIS, name3, value3, convention=convESMF, &
      purpose=purpGen, rc=status)
    call ESMF_AttributeSet(PHIS, name4, value4, convention=convESMF, &
      purpose=purpGen, rc=status)
    if (status .ne. ESMF_SUCCESS) return
 
    value1 = 'QTR'
    value2 = ''
    value3 = 'Advected quantities'
    value4 = 'unknown'
      
    QTR = ESMF_FieldCreate(grid, arrayspec=arrayspec, &
              staggerloc=ESMF_STAGGERLOC_CENTER, rc=status)
    call ESMF_AttributeAdd(QTR, convention=convESMF, purpose=purpGen, &
      rc=status)
    call ESMF_AttributeSet(QTR, name1, value1, convention=convESMF, &
      purpose=purpGen, rc=status)
    call ESMF_AttributeSet(QTR, name2, value2, convention=convESMF, &
      purpose=purpGen, rc=status)
    call ESMF_AttributeSet(QTR, name3, value3, convention=convESMF, &
      purpose=purpGen, rc=status)
    call ESMF_AttributeSet(QTR, name4, value4, convention=convESMF, &
      purpose=purpGen, rc=status)
    if (status .ne. ESMF_SUCCESS) return
 
    value1 = 'CNV'
    value2 = 'atmosphere_kinetic_energy_content'
    value3 = 'Generation of atmosphere kinetic energy content'
    value4 = 'W m-2'
      
    CNV = ESMF_FieldCreate(grid, arrayspec=arrayspec, &
              staggerloc=ESMF_STAGGERLOC_CENTER, rc=status)
    call ESMF_AttributeAdd(CNV, convention=convESMF, purpose=purpGen, &
      rc=status)
    call ESMF_AttributeSet(CNV, name1, value1, convention=convESMF, &
      purpose=purpGen, rc=status)
    call ESMF_AttributeSet(CNV, name2, value2, convention=convESMF, &
      purpose=purpGen, rc=status)
    call ESMF_AttributeSet(CNV, name3, value3, convention=convESMF, &
      purpose=purpGen, rc=status)
    call ESMF_AttributeSet(CNV, name4, value4, convention=convESMF, &
      purpose=purpGen, rc=status)
    if (status .ne. ESMF_SUCCESS) return
 
    value1 = 'CONVCPT'
    value2 = ''
    value3 = 'Vertically integrated enthalpy convergence'
    value4 = 'W m-2'
      
    CONVCPT = ESMF_FieldCreate(grid, arrayspec=arrayspec, &
              staggerloc=ESMF_STAGGERLOC_CENTER, rc=status)
    call ESMF_AttributeAdd(CONVCPT, convention=convESMF, purpose=purpGen, &
      rc=status)
    call ESMF_AttributeSet(CONVCPT, name1, value1, convention=convESMF, &
      purpose=purpGen, rc=status)
    call ESMF_AttributeSet(CONVCPT, name2, value2, convention=convESMF, &
      purpose=purpGen, rc=status)
    call ESMF_AttributeSet(CONVCPT, name3, value3, convention=convESMF, &
      purpose=purpGen, rc=status)
    call ESMF_AttributeSet(CONVCPT, name4, value4, convention=convESMF, &
      purpose=purpGen, rc=status)
    if (status .ne. ESMF_SUCCESS) return
 
    value1 = 'CONVKE'
    value2 = ''
    value3 = 'Vertically integrated kinetic energy convergence'
    value4 = 'W m-2'
      
    CONVKE = ESMF_FieldCreate(grid, arrayspec=arrayspec, &
              staggerloc=ESMF_STAGGERLOC_CENTER, rc=status)
    call ESMF_AttributeAdd(CONVKE, convention=convESMF, purpose=purpGen, &
      rc=status)
    call ESMF_AttributeSet(CONVKE, name1, value1, convention=convESMF, &
      purpose=purpGen, rc=status)
    call ESMF_AttributeSet(CONVKE, name2, value2, convention=convESMF, &
      purpose=purpGen, rc=status)
    call ESMF_AttributeSet(CONVKE, name3, value3, convention=convESMF, &
      purpose=purpGen, rc=status)
    call ESMF_AttributeSet(CONVKE, name4, value4, convention=convESMF, &
      purpose=purpGen, rc=status)
    if (status .ne. ESMF_SUCCESS) return
 
    value1 = 'CONVPHI'
    value2 = ''
    value3 = 'Vertically integrated geopotential convergence'
    value4 = 'W m-2'
      
    CONVPHI = ESMF_FieldCreate(grid, arrayspec=arrayspec, &
              staggerloc=ESMF_STAGGERLOC_CENTER, rc=status)
    call ESMF_AttributeAdd(CONVPHI, convention=convESMF, purpose=purpGen, &
      rc=status)
    call ESMF_AttributeSet(CONVPHI, name1, value1, convention=convESMF, &
      purpose=purpGen, rc=status)
    call ESMF_AttributeSet(CONVPHI, name2, value2, convention=convESMF, &
      purpose=purpGen, rc=status)
    call ESMF_AttributeSet(CONVPHI, name3, value3, convention=convESMF, &
      purpose=purpGen, rc=status)
    call ESMF_AttributeSet(CONVPHI, name4, value4, convention=convESMF, &
      purpose=purpGen, rc=status)
    if (status .ne. ESMF_SUCCESS) return

    ! Create the Grid Attribute Package
    call ESMF_AttributeAdd(grid,convention=convESMF, purpose=purpGen, rc=status)
    call ESMF_AttributeSet(grid,'DimOrder','YX',convention=convESMF, purpose=purpGen, rc=status)
    call ESMF_AttributeSet(grid,'GridType','Cubed sphere',convention=convESMF, purpose=purpGen, rc=status)    
    call ESMF_AttributeSet(grid,'CongruentTiles',.true.,convention=convESMF, purpose=purpGen, rc=status)
    call ESMF_AttributeSet(grid,'NorthPoleLocation','long: 0.0 lat: 90.0',convention=convESMF, purpose=purpGen, rc=status)
    call ESMF_AttributeSet(grid,'NumberOfCells','53457',convention=convESMF, purpose=purpGen, rc=status)
    call ESMF_AttributeSet(grid,'NumDims','2',convention=convESMF, purpose=purpGen, rc=status)
    call ESMF_AttributeSet(grid,'NX','96',convention=convESMF, purpose=purpGen, rc=status)
    call ESMF_AttributeSet(grid,'NY','96',convention=convESMF, purpose=purpGen, rc=status)
    call ESMF_AttributeSet(grid,'NZ','15',convention=convESMF, purpose=purpGen, rc=status)
    call ESMF_AttributeSet(grid,'Resolution','C48',convention=convESMF, purpose=purpGen, rc=status)
    call ESMF_AttributeSet(grid,'IsConformal',.false.,convention=convESMF, purpose=purpGen, rc=status)
    call ESMF_AttributeSet(grid,'IsRegular',.false.,convention=convESMF, purpose=purpGen, rc=status)
    call ESMF_AttributeSet(grid,'IsUniform',.false.,convention=convESMF, purpose=purpGen, rc=status)
    call ESMF_AttributeSet(grid,'IsPoleCovered',.true.,convention=convESMF, purpose=purpGen, rc=status)
    call ESMF_AttributeSet(grid,'DiscretizationType','Logically Rectangular',convention=convESMF, purpose=purpGen, rc=status)
    call ESMF_AttributeSet(grid,'GeometryType','Sphere',convention=convESMF, purpose=purpGen, rc=status)
    if (status .ne. ESMF_SUCCESS) return

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.

    fbundle = ESMF_FieldBundleCreate(name="fbundle", rc=status)
    call ESMF_FieldBundleSetGrid(fbundle, grid=grid, rc=status)
    if (status .ne. ESMF_SUCCESS) return
      
    call ESMF_FieldBundleAdd(fbundle, DPEDT, rc=status)
    call ESMF_FieldBundleAdd(fbundle, DTDT, rc=status)
    call ESMF_FieldBundleAdd(fbundle, DUDT, rc=status)
    call ESMF_FieldBundleAdd(fbundle, DVDT, rc=status)
    call ESMF_FieldBundleAdd(fbundle, PHIS, rc=status)
    call ESMF_FieldBundleAdd(fbundle, QTR, rc=status)
    call ESMF_FieldBundleAdd(fbundle, CNV, rc=status)
    call ESMF_FieldBundleAdd(fbundle, CONVCPT, rc=status)
    call ESMF_FieldBundleAdd(fbundle, CONVKE, rc=status)
    call ESMF_FieldBundleAdd(fbundle, CONVPHI, rc=status)
    if (status .ne. ESMF_SUCCESS) return

    call ESMF_StateAdd(exportState, fieldbundle=fbundle, rc=status)
    if (status .ne. ESMF_SUCCESS) return

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)
    if (rc/=ESMF_SUCCESS) return
    call ESMF_StateReconcile(importState, vm, attreconflag=ESMF_ATTRECONCILE_ON, rc=rc)
    if (rc/=ESMF_SUCCESS) return
    call ESMF_StateReconcile(exportState, vm, attreconflag=ESMF_ATTRECONCILE_ON, rc=rc)
    if (rc/=ESMF_SUCCESS) return

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,convCC,purpGen,name3
    character(ESMF_MAXSTR),dimension(2) :: attrList
    type(ESMF_Field)            :: field
    type(ESMF_FieldBundle)      :: fbundle
    type(ESMF_Grid)             :: grid

    rc = ESMF_SUCCESS

    convESMF = 'ESMF'
    convCC = 'CustomConvention'
    purpGen = 'General'
    name2 = 'StandardName'
    value2 = 'default_standard_name'
    name3 = 'LongName'
    
    attrList(1) = 'coordinates'
    attrList(2) = 'mask'
    
    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

    call ESMF_StateGet(exportState, "fbundle", fbundle, rc=rc)
    if (rc/=ESMF_SUCCESS) return
    call ESMF_FieldBundleGet(fbundle, grid=grid, rc=rc)
    if (rc/=ESMF_SUCCESS) return

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(fbundle, fieldIndex=k, field=field, rc=rc)
        if (rc/=ESMF_SUCCESS) return
        call ESMF_AttributeSet(field, name2, value2, convention=convESMF, &
          purpose=purpGen, rc=status)
        if (rc/=ESMF_SUCCESS) return
        call ESMF_AttributeAdd(field, convention=convCC, purpose=purpGen, &
          attrList=attrList, nestConvention=convESMF, nestPurpose=purpGen, rc=rc)
        call ESMF_AttributeSet(field, name='Coordinates', value='Latlon', &
          convention=convCC, purpose=purpGen, rc=rc)
        call ESMF_AttributeSet(field, name='Mask', value='Yes', &
          convention=convCC, purpose=purpGen, rc=rc)
        if (rc/=ESMF_SUCCESS) return
        call ESMF_AttributeRemove(field, name=name3, convention=convESMF, &
          purpose=purpGen, rc=status)
        if (rc/=ESMF_SUCCESS) return
    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)
    if (rc/=ESMF_SUCCESS) return
    call ESMF_VMGet(vm, localPet=myPet, rc=rc)
    if (rc/=ESMF_SUCCESS) return

    call ESMF_StateGet(importState, rc=rc)
    if (rc/=ESMF_SUCCESS) return
    call ESMF_StateGet(exportState, rc=rc)
    if (rc/=ESMF_SUCCESS) return

    rootList = (/0,1/)
    call ESMF_AttributeUpdate(importState, vm, rootList=rootList, rc=rc)
    if (rc/=ESMF_SUCCESS) return
   
    call ESMF_AttributeCopy(importState, exportState, &
      ESMF_ATTCOPY_HYBRID, ESMF_ATTTREE_ON, rc=rc)
    if (rc/=ESMF_SUCCESS) return

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. Next we will use the writing capabilities of the Attribute class, soon to be replaced by the ESMF I/O class. We will first 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.

31.3.4 Example: Reading an XML file-based ESG Attribute Package for a Gridded Component

This example shows how to read an ESG Attribute Package for a Gridded Component from an XML file. The XML file contains Attribute values filled-in by the user. The standard ESG Component Attribute Package is supplied with ESMF and is defined in an XSD file, which is used to validate the XML file. See
ESMF_DIR/src/Superstructure/Component/etc/esmf_gridcomp.xml (Attribute Package values) and
ESMF_DIR/src/Superstructure/Component/etc/esmf_comp.xsd (Attribute Package definition).

      ! ESMF Framework module
      use ESMF_Mod
      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, 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 "Name" Attribute from a GridComp
      call ESMF_AttributeGet(gridcomp, name='Name', value=attrValue, &
                             convention='ESG', purpose='General', rc=rc)

      ! Get ESG "FullName" Attribute from a GridComp
      call ESMF_AttributeGet(gridcomp, name='FullName', 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)

      ! Get CF "Comment" Attribute from a GridComp
      call ESMF_AttributeGet(gridcomp, name='Comment', value=attrValue, &
                             convention='CF', purpose='General', rc=rc)

      ! Get CF "References" Attribute from a GridComp
      call ESMF_AttributeGet(gridcomp, name='References', value=attrValue, &
                             convention='CF', purpose='General', rc=rc)

      call ESMF_GridCompDestroy(gridcomp, rc=rc)

      ! finalize ESMF framework
      call ESMF_Finalize(rc=rc)

31.3.5 Example: Reading an XML file-based CF Attribute Package for a Field

This example shows how to read a CF Attribute Package for a Field from an XML file. The XML file contains Attribute values filled-in by the user. The standard CF Attribute Package is supplied with ESMF and is defined in an XSD file, which is used to validate the XML file. See
ESMF_DIR/src/Infrastructure/Field/etc/esmf_field.xml (Attribute Package values) and
ESMF_DIR/src/Infrastructure/Field/etc/esmf_field.xsd (Attribute Package definition).

      ! ESMF Framework module
      use ESMF_Mod
      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, rc=rc)

      ! Create a field
      field = ESMF_FieldCreateEmpty(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 "Name" Attribute from a Field
      call ESMF_AttributeGet(field, name='Name', 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)

31.3.6 Example: Reading an XML file-based GridSpec Attribute Package for a Grid

This example shows how to read a GridSpec Attribute Package from an XML file. The XML file contains Attribute values filled-in by the user. The standard GridSpec Attribute Package is supplied with ESMF and is defined in an XSD file, which is used to validate the XML file. See
ESMF_DIR/src/Infrastructure/Grid/etc/esmf_grid.xml (Attribute Package values) and
ESMF_DIR/src/Infrastructure/Grid/etc/esmf_grid.xsd (Attribute Package definition)

      ! ESMF Framework module
      use ESMF_Mod
      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, rc=rc)

      ! Create a grid
      grid = ESMF_GridCreateEmpty(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 "CongruentTiles" Attribute from a Grid
      call ESMF_AttributeGet(grid, name='CongruentTiles', value=attrValue, &
                             convention='GridSpec', purpose='General', 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 "DimOrder" Attribute from a Grid
      call ESMF_AttributeGet(grid, name='DimOrder', 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 "IsPoleCovered" Attribute from a Grid
      call ESMF_AttributeGet(grid, name='IsPoleCovered', 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 "NumDims" Attribute from a Grid
      call ESMF_AttributeGet(grid, name='NumDims', 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 "NZ" Attribute from a Grid
      call ESMF_AttributeGet(grid, name='NZ', value=attrValue, &
                             convention='GridSpec', purpose='General', rc=rc)

      ! Get GridSpec "Resolution" Attribute from a Grid
      call ESMF_AttributeGet(grid, name='Resolution', value=attrValue, &
                             convention='GridSpec', purpose='General', rc=rc)

      call ESMF_GridDestroy(grid, rc=rc)

      ! finalize ESMF framework
      call ESMF_Finalize(rc=rc)

31.3.7 Example: Read and validate an XML file-based set of user-defined Attributes for a Coupler Component

This example shows how to read and validate, from an XML and XSD file, respectively, a set of user-defined custom Attributes for a Coupler Component. See
ESMF_DIR/src/Superstructure/Component/etc/custom_cplcomp.xml (Attribute values) and
ESMF_DIR/src/Superstructure/Component/etc/custom_cplcomp.xsd (Attribute definitions)

      ! ESMF Framework module
      use ESMF_Mod
      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, 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)

31.4 Restrictions and Future Work

The capabilities of the Attribute class which are still in the developmental stage are listed by category.

31.4.1 Attributes

31.4.2 Attribute Hierarchies

31.4.3 Attribute Packages

31.5 Design and Implementation Notes

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.

31.5.1 Attribute Memory Deallocation

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.

31.5.2 Using ESMF_AttributeGet() to retrieve Attribute lists

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.

31.5.3 Using Attribute package nesting capabilites

There is a recommended practice when using nested Attribute packages to organize metadata conventions. 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 recommend 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. Thus, by removing the ESG Attribute package on a Field, the CF and Attribute package will also be removed.


31.5.4 Attributes in a Distributed Environment

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 call 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. 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.

31.5.5 Writing Attribute packages to file

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 specifiers throughout an entire ESMF object hierarchy. The files are written in either tab-delimited or XML format, which is controlled by an optional flag in the interface.

This 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 flag that is used to determine which format for writing the Attribute packages is called the ESMF_AttWriteFlag. It can take values of ESMF_ATTWRITE_TAB or ESMF_ATTWRITE_XML, where the default value is the former option. In both cases the write files will end up in the execution directory after they are written and closed. The tab-delimited file will have an ending of .stdout, and the XML file will have an ending of .xml. In both cases the file will be named for the name of the ESMF object from which ESMF_AttributeWrite() was called.

31.5.6 Copying Attribute hierarchies

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 States. 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_AttCopyFlag to be set to ESMF_ATTCOPY_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_AttCopyFlag to ESMF_ATTCOPY_HYBRID 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.

31.5.7 Reading/Writing Attributes from XML files

The Xerces C++ library, v3.1.0 or better, is used to read and write 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/.

31.6 Class API

31.6.1 ESMF_AttributeAdd - Add an ESMF standard Attribute package


INTERFACE:

   ! Private name; call using ESMF_AttributeAdd()
   subroutine ESMF_AttAddPackStandard(<object>, convention, purpose, 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 :: nestConvention
   character (len = *), intent(in), optional :: nestPurpose
   integer, intent(out), optional :: rc
DESCRIPTION:

Add an ESMF standard Attribute package. See Section 31.1.3 for a description of Attribute packages and their conventions, purposes, and object types.

Supported values for <object> are:

type(ESMF_Array), intent(inout) :: array
type(ESMF_CplComp), intent(inout) :: comp
type(ESMF_GridComp), intent(inout) :: comp
type(ESMF_Field), intent(inout) :: field
type(ESMF_Grid), intent(inout) :: grid
type(ESMF_State), intent(inout) :: state

The arguments are:

<object>
An ESMF object
convention
The convention of the new Attribute package
purpose
The purpose of the new Attribute package
[nestConvention]
The convention of the Attribute package around which to nest the new Attribute package
[nestPurpose]
The purpose of the Attribute package around which to nest the new Attribute package
[rc]
Return code; equals ESMF_SUCCESS if there are no errors

31.6.2 ESMF_AttributeAdd - Add a custom Attribute package or modify an existing Attribute package


INTERFACE:

   ! Private name; call using ESMF_AttributeAdd()
   subroutine ESMF_AttAddPackCstm(<object>, convention, purpose, &
   attrList, count, nestConvention, nestPurpose, rc)
ARGUMENTS:
   <object>, see below for supported values
   character (len = *), intent(in), optional :: convention
   character (len = *), intent(in), optional :: purpose
   character (len=*), dimension(:), intent(in) :: attrList
   integer, intent(in), optional :: count
   character (len = *), intent(in), optional :: nestConvention
   character (len = *), intent(in), optional :: nestPurpose
   integer, intent(out), optional :: rc
DESCRIPTION:

Add a custom Attribute package to <object>. See Section 31.1.3 for a description of Attribute packages and their conventions, purposes, and object types.

Supported values for <object> are:

type(ESMF_Array), intent(inout) :: array
type(ESMF_ArrayBundle), intent(inout) :: arraybundle
type(ESMF_CplComp), intent(inout) :: comp
type(ESMF_GridComp), intent(inout) :: comp
type(ESMF_DistGrid), intent(inout) :: distgrid
type(ESMF_Field), intent(inout) :: field
type(ESMF_FieldBundle), intent(inout) :: fieldbundle
type(ESMF_Grid), intent(inout) :: grid
type(ESMF_State), intent(inout) :: state

The arguments are:

<object>
An ESMF object
convention
The convention of the Attribute package
purpose
The purpose of the Attribute package
attrList
The list of Attribute names to specify the custom Attribute package
[count]
The number of Attributes to add to the custom Attribute package
[nestConvention]
The convention of the Attribute package around which to nest the new Attribute package
[nestPurpose]
The purpose of the Attribute package around which to nest the new Attribute package
[rc]
Return code; equals ESMF_SUCCESS if there are no errors

31.6.3 ESMF_AttributeCopy - Copy an Attribute hierarchy


INTERFACE:

   ! Private name; call using ESMF_AttributeCopy()
   subroutine ESMF_AttributeCopy(<object1>, <object2>, attcopyflag, atttreeflag, rc)
ARGUMENTS:
   <object1>, see below for supported values
   <object2>, see below for supported values
   type(ESMF_AttCopyFlag), intent(in) :: attcopyflag
   type(ESMF_AttTreeFlag), intent(in) :: atttreeflag
   integer, intent(out), optional :: rc
DESCRIPTION:

Copy an Attribute hierarchy from <object1> to <object2>. Supported values for <object1> are:

type(ESMF_CplComp), intent(inout) :: comp1
type(ESMF_GridComp), intent(inout) :: comp1
type(ESMF_State), intent(inout) :: state
Supported values for <object2> are:
type(ESMF_CplComp), intent(inout) :: comp2
type(ESMF_GridComp), intent(inout) :: comp2
type(ESMF_State), intent(inout) :: state

NOTE: Copies between different ESMF objects are not possible at this time.

The arguments are:

<object1>
An ESMF object
<object2>
An ESMF object
attcopyflag
A flag to determine if the copy is to be by reference, value, or both
atttreeflag
A flag to determine if the copy is supposed to descend the Attribute hierarchy
[rc]
Return code; equals ESMF_SUCCESS if there are no errors

NOTE: Not all combinations of copy flags are enabled at this time. See the reference manual for an overview of the options available for ESMF_AttributeCopy(). The options for attcopyflag include:

  1. ESMF_ATTCOPY_HYBRID will copy the top base level Attributes by value, and all others by reference
  2. ESMF_ATTCOPY_REFERENCE will copy all Attributes by reference
  3. ESMF_ATTCOPY_VALUE will copy all Attributes by value
The options for atttreeflag include:
  1. ESMF_ATTTREE_OFF will only descend the first base level of the Attribute hierarchy
  2. ESMF_ATTTREE_ON will descend the entire Attribute hierarchy

31.6.4 ESMF_AttributeGet - Get an Attribute


INTERFACE:

   subroutine ESMF_AttributeGet(<object>, name, <value argument>, &
   <defaultvalue argument>, convention, purpose, 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
   integer, intent(out), optional :: rc
DESCRIPTION:

Return an Attribute value from the <object>, or from the Attribute package specified by convention and purpose. A default value argument may be given if a return code is not desired when the Attribute is not found. See Section 31.1.3 for a description of Attribute packages and their conventions, purposes, and object types.

Supported values for <object> are:

type(ESMF_Array), intent(inout) :: array
type(ESMF_ArrayBundle), intent(inout) :: arraybundle
type(ESMF_CplComp), intent(inout) :: comp
type(ESMF_GridComp), intent(inout) :: comp
type(ESMF_DistGrid), intent(inout) :: distgrid
type(ESMF_Field), intent(inout) :: field
type(ESMF_FieldBundle), intent(inout) :: fieldbundle
type(ESMF_Grid), intent(inout) :: grid
type(ESMF_State), intent(inout) :: state
Supported values for <value argument> are:
integer(ESMF_KIND_I4), intent(out) :: value
integer(ESMF_KIND_I8), intent(out) :: value
real (ESMF_KIND_R4), intent(out) :: value
real (ESMF_KIND_R8), intent(out) :: value
logical, intent(out) :: value
character (len = *), intent(out), value
Supported values for <defaultvalue argument> are:
integer(ESMF_KIND_I4), intent(out), optional :: defaultvalue
integer(ESMF_KIND_I8), intent(out), optional :: defaultvalue
real (ESMF_KIND_R4), intent(out), optional :: defaultvalue
real (ESMF_KIND_R8), intent(out), optional :: defaultvalue
logical, intent(out), optional :: defaultvalue
character (len = *), intent(out), optional :: defaultvalue

The arguments are:

<object>
An ESMF object
name
The name of the Attribute to retrieve
<value argument>
The value of the named Attribute
[<defaultvalue argument>]
The default value of the named Attribute
[convention]
The convention of the Attribute package
[purpose]
The purpose of the Attribute package
[rc]
Return code; equals ESMF_SUCCESS if there are no errors

31.6.5 ESMF_AttributeGet - Get an Attribute


INTERFACE:

   subroutine ESMF_AttributeGet(<object>, name, <valueList argument>, &
   <defaultvalueList argument>, convention, purpose, &
   itemCount, 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
   integer, intent(inout), optional :: itemCount
   integer, intent(out), optional :: rc
DESCRIPTION:

Return an Attribute value from the <object>, or from the Attribute package specified by convention and purpose. A default value argument may be given if a return code is not desired when the Attribute is not found. See Section 31.1.3 for a description of Attribute packages and their conventions, purposes, and object types.

Supported values for <object> are:

type(ESMF_Array), intent(inout) :: array
type(ESMF_ArrayBundle), intent(inout) :: arraybundle
type(ESMF_CplComp), intent(inout) :: comp
type(ESMF_GridComp), intent(inout) :: comp
type(ESMF_DistGrid), intent(inout) :: distgrid
type(ESMF_Field), intent(inout) :: field
type(ESMF_FieldBundle), intent(inout) :: fieldbundle
type(ESMF_Grid), intent(inout) :: grid
type(ESMF_State), intent(inout) :: state
Supported values for <value argument> are:
integer(ESMF_KIND_I4), dimension(:), intent(out) :: valueList
integer(ESMF_KIND_I8), dimension(:), intent(out) :: valueList
real (ESMF_KIND_R4), dimension(:), intent(out) :: valueList
real (ESMF_KIND_R8), dimension(:), intent(out) :: valueList
logical, dimension(:), intent(out) :: valueList
character (len = *), dimension(count), intent(out) :: valueList
Supported values for <defaultvalue argument> are:
integer(ESMF_KIND_I4), dimension(:), intent(out), optional :: defaultvalueList
integer(ESMF_KIND_I8), dimension(:), intent(out), optional :: defaultvalueList
real (ESMF_KIND_R4), dimension(:), intent(out), optional :: defaultvalueList
real (ESMF_KIND_R8), dimension(:), intent(out), optional :: defaultvalueList
logical, dimension(:), intent(out), optional :: defaultvalueList
character (len = *), dimension(:), intent(out), optional :: defaultvalueList

The arguments are:

<object>
An ESMF object
name
The name of the Attribute to retrieve
<valueList argument>
The valueList of the named Attribute
[<defaultvalueList argument>]
The default value list of the named Attribute
[convention]
The convention of the Attribute package
[purpose]
The purpose of the Attribute package
[itemCount]
The number of items in a multi-valued Attribute. If the itemCount is passed in, only itemCount items of the desired Attribute will be returned, as long as there is enough space and there are itemCount items to return. Regardless of whether itemCount is passed in, it will be returned as the number of items that was actually returned.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors

31.6.6 ESMF_AttributeGet - Get the Attribute count


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_AttCountFlag), intent(in), optional :: attcountflag
   integer, intent(out), optional :: rc
DESCRIPTION:

Return the Attribute count for <object>. Supported values for <object> are:

type(ESMF_Array), intent(inout) :: array
type(ESMF_ArrayBundle), intent(inout) :: arraybundle
type(ESMF_CplComp), intent(inout) :: comp
type(ESMF_GridComp), intent(inout) :: comp
type(ESMF_DistGrid), intent(inout) :: distgrid
type(ESMF_Field), intent(inout) :: field
type(ESMF_FieldBundle), intent(inout) :: fieldbundle
type(ESMF_Grid), intent(inout) :: grid
type(ESMF_State), intent(inout) :: state

The arguments are:

<object>
An ESMF object
count
The Attribute count for <object>
[attcountflag]
The flag to specify which attribute count to return, the default is ESMF_ATTGETCOUNT_ATTRIBUTE (see below)
[rc]
Return code; equals ESMF_SUCCESS if there are no errors

NOTE: The options for attcountflag include:

  1. ESMF_ATTGETCOUNT_ATTRIBUTE will get the number of single Attributes
  2. ESMF_ATTGETCOUNT_ATTPACK will get the number of Attribute packages
  3. ESMF_ATTGETCOUNT_ATTLINK will get the number of Attribute links
  4. ESMF_ATTGETCOUNT_TOTAL will get the total number of Attributes

31.6.7 ESMF_AttributeGet - Get Attribute info by name


INTERFACE:

   ! Private name; call using ESMF_AttributeGet()
   subroutine ESMF_AttributeGetInfoByNam(<object>, name, typekind, itemCount, rc)
ARGUMENTS:
   <object>, see below for supported values
   character (len = *), intent(in) :: name
   type(ESMF_TypeKind), intent(out), optional :: typekind
   integer, intent(out), optional :: itemCount
   integer, intent(out), optional :: rc
DESCRIPTION:

Return information associated with the named Attribute, including typekind and itemCount. Supported values for <object> are:

type(ESMF_Array), intent(inout) :: array
type(ESMF_ArrayBundle), intent(inout) :: arraybundle
type(ESMF_CplComp), intent(inout) :: comp
type(ESMF_GridComp), intent(inout) :: comp
type(ESMF_DistGrid), intent(inout) :: distgrid
type(ESMF_Field), intent(inout) :: field
type(ESMF_FieldBundle), intent(inout) :: fieldbundle
type(ESMF_Grid), intent(inout) :: grid
type(ESMF_State), intent(inout) :: state

The arguments are:

<object>
An ESMF object
name
The name of the Attribute to query
[typekind
] The typekind of the Attribute
[itemCount]
The number of items in this Attribute
[rc]
Return code; equals ESMF_SUCCESS if there are no errors

31.6.8 ESMF_AttributeGet - Get Attribute info by index number


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), intent(out), optional :: typekind
   integer, intent(out), optional :: itemCount
   integer, intent(out), optional :: rc
DESCRIPTION:

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:

type(ESMF_Array), intent(inout) :: array
type(ESMF_ArrayBundle), intent(inout) :: arraybundle
type(ESMF_CplComp), intent(inout) :: comp
type(ESMF_GridComp), intent(inout) :: comp
type(ESMF_DistGrid), intent(inout) :: distgrid
type(ESMF_Field), intent(inout) :: field
type(ESMF_FieldBundle), intent(inout) :: fieldbundle
type(ESMF_Grid), intent(inout) :: grid
type(ESMF_State), intent(inout) :: state

The arguments are:

<object>
An ESMF object
attributeIndex
The index number of the Attribute to query
name
The name of the Attribute
[typekind]
The typekind of the Attribute
[itemCount]
The number of items in this Attribute
[rc]
Return code; equals ESMF_SUCCESS if there are no errors

31.6.9 ESMF_AttributeLink - Link a Component Attribute hierarchy to that of a Component or State


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 :: rc
DESCRIPTION:

Attach a CplComp or GridComp Attribute hierarchy to the hierarchy of a CplComp, GridComp, or State. Supported values for the <object1> are:

type(ESMF_CplComp), intent(inout) :: comp1
type(ESMF_GridComp), intent(inout) :: comp1
Supported values for the <object2> are:
type(ESMF_CplComp), intent(inout) :: comp2
type(ESMF_GridComp), intent(inout) :: comp2
type(ESMF_State), intent(inout) :: state

The arguments are:

<object1>
The ``parent'' object in the Attribute hierarchy link
<object2>
The ``child'' object in the Attribute hierarchy link
[rc]
Return code; equals ESMF_SUCCESS if there are no errors

31.6.10 ESMF_AttributeLink - Link a State Attribute hierarchy with the

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 :: rc
DESCRIPTION:

Attach a State Attribute hierarchy to the hierarchy of a Fieldbundle, Field, or another State. Supported values for the <object> are:

type(ESMF_Array), intent(inout) :: array
type(ESMF_ArrayBundle), intent(inout) :: arraybundle
type(ESMF_Field), intent(inout) :: field
type(ESMF_FieldBundle), intent(inout) :: fieldbundle
type(ESMF_State), intent(inout) :: state

The arguments are:

state
An ESMF_State object
<object>
The object with which to link hierarchies
[rc]
Return code; equals ESMF_SUCCESS if there are no errors

31.6.11 ESMF_AttributeLink - Link a FieldBundle and Field Attribute hierarchy


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 :: rc
DESCRIPTION:

Attach a FieldBundle Attribute hierarchy to the hierarchy of a Field.

The arguments are:

fieldbundle
An ESMF_FieldBundle object
field
An ESMF_Field object
[rc]
Return code; equals ESMF_SUCCESS if there are no errors

31.6.12 ESMF_AttributeLink - Link a Field and Grid Attribute hierarchy


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 :: rc
DESCRIPTION:

Attach a Field Attribute hierarchy to the hierarchy of a Grid.

The arguments are:

field
An ESMF_Field object
grid
An ESMF_Grid object
[rc]
Return code; equals ESMF_SUCCESS if there are no errors

31.6.13 ESMF_AttributeLink - Link an ArrayBundle and Array Attribute hierarchy


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 :: rc
DESCRIPTION:

Attach an ArrayBundle Attribute hierarchy to the hierarchy of an Array.

The arguments are:

arraybundle
An ESMF_ArrayBundle object
array
An ESMF_Array object
[rc]
Return code; equals ESMF_SUCCESS if there are no errors

31.6.14 ESMF_AttributeLinkRemove - Unlink a Component Attribute hierarchy from that of a Component or State


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 :: rc
DESCRIPTION:

Unattach a CplComp or GridComp Attribute hierarchy from the hierarchy of a CplComp, GridComp, or State. Supported values for the <object1> are:

type(ESMF_CplComp), intent(inout) :: comp1
type(ESMF_GridComp), intent(inout) :: comp1
Supported values for the <object2> are:
type(ESMF_CplComp), intent(inout) :: comp2
type(ESMF_GridComp), intent(inout) :: comp2
type(ESMF_State), intent(inout) :: state

The arguments are:

<object1>
The ``parent'' object in the Attribute hierarchy link
<object2>
The ``child'' object in the Attribute hierarchy link
[rc]
Return code; equals ESMF_SUCCESS if there are no errors

31.6.15 ESMF_AttributeLinkRemove - Unlink a State Attribute hierarchy with

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 :: rc
DESCRIPTION:

Unattach a State Attribute hierarchy from the hierarchy of a Fieldbundle, Field, or another State. Supported values for the <object> are:

type(ESMF_Array), intent(inout) :: array
type(ESMF_ArrayBundle), intent(inout) :: arraybundle
type(ESMF_Field), intent(inout) :: field
type(ESMF_FieldBundle), intent(inout) :: fieldbundle
type(ESMF_State), intent(inout) :: state

The arguments are:

state
An ESMF_State object
<object>
The object with which to unlink hierarchies
[rc]
Return code; equals ESMF_SUCCESS if there are no errors

31.6.16 ESMF_AttributeLinkRemove - Unlink a FieldBundle and Field Attribute hierarchy


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 :: rc
DESCRIPTION:

Unattach a FieldBundle Attribute hierarchy from the hierarchy of a Field.

The arguments are:

fieldbundle
An ESMF_FieldBundle object
field
An ESMF_Field object
[rc]
Return code; equals ESMF_SUCCESS if there are no errors

31.6.17 ESMF_AttributeLinkRemove - Unlink a Field and Grid Attribute hierarchy


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 :: rc
DESCRIPTION:

Unattach a Field Attribute hierarchy from the hierarchy of a Grid.

The arguments are:

field
An ESMF_Field object
grid
An ESMF_Grid object
[rc]
Return code; equals ESMF_SUCCESS if there are no errors

31.6.18 ESMF_AttributeLinkRemove - Unlink an ArrayBundle and Array Attribute hierarchy


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 :: rc
DESCRIPTION:

Unattach an ArrayBundle Attribute hierarchy from the hierarchy of an Array.

The arguments are:

arraybundle
An ESMF_ArrayBundle object
array
An ESMF_Array object
[rc]
Return code; equals ESMF_SUCCESS if there are no errors

31.6.19 ESMF_AttributeRead - Read Attributes from an XML file


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 :: rc
DESCRIPTION:

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 31.1.3 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".

Supported values for <object> are:

type(ESMF_Array), intent(inout) :: array ! not yet implemented
type(ESMF_ArrayBundle), intent(inout) :: arrayBundle ! not yet implemented
type(ESMF_CplComp), intent(inout) :: cplComp
type(ESMF_GridComp), intent(inout) :: gridComp
type(ESMF_Field), intent(inout) :: field
type(ESMF_FieldBundle), intent(inout) :: fieldBundle ! not yet implemented
type(ESMF_Grid), intent(inout) :: grid
type(ESMF_DistGrid), intent(inout) :: distGrid ! not yet implemented

The arguments are:

<object>
The ESMF object onto which the read Attributes will be placed
[fileName]
The name of the XML file to read
[schemaFileName]
The name of the XSD file to validate the contents of fileName
[convention]
The convention of the Attribute package to read
[purpose]
The purpose of the Attribute package to read
[rc]
Return code; equals ESMF_SUCCESS if there are no errors

31.6.20 ESMF_AttributeRemove - Remove an Attribute or Attribute package


INTERFACE:

   subroutine ESMF_AttributeRemove(<object>, name, convention, purpose, 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
   integer, intent(out), optional :: rc
DESCRIPTION:

Remove an Attribute, or Attribute package on <object>. See Section 31.1.3 for a description of Attribute packages and their conventions, purposes, and object types.

Supported values for <object> are:

type(ESMF_Array), intent(inout) :: array
type(ESMF_ArrayBundle), intent(inout) :: arraybundle
type(ESMF_CplComp), intent(inout) :: comp
type(ESMF_GridComp), intent(inout) :: comp
type(ESMF_DistGrid), intent(inout) :: distgrid
type(ESMF_Field), intent(inout) :: field
type(ESMF_FieldBundle), intent(inout) :: fieldbundle
type(ESMF_Grid), intent(inout) :: grid
type(ESMF_State), intent(inout) :: state

The arguments are:

<object>
An ESMF object
[name]
The name of the Attribute to remove
[convention]
The convention of the Attribute package
[purpose]
The purpose of the Attribute package
[rc]
Return code; equals ESMF_SUCCESS if there are no errors

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.

31.6.21 ESMF_AttributeSet - Set an Attribute


INTERFACE:

   subroutine ESMF_AttributeSet(<object>, name, <value argument>, &
   convention, purpose, 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
   integer, intent(out), optional :: rc
DESCRIPTION:

Attach an Attribute to <object>, or set an Attribute in an Attribute package. The Attribute has a name and either a value, and a convention and purpose. See Section 31.1.3 for a description of Attribute packages and their conventions, purposes, and object types.

Supported values for <object> are:

type(ESMF_Array), intent(inout) :: array
type(ESMF_ArrayBundle), intent(inout) :: arraybundle
type(ESMF_CplComp), intent(inout) :: comp
type(ESMF_GridComp), intent(inout) :: comp
type(ESMF_DistGrid), intent(inout) :: distgrid
type(ESMF_Field), intent(inout) :: field
type(ESMF_FieldBundle), intent(inout) :: fieldbundle
type(ESMF_Grid), intent(inout) :: grid
type(ESMF_State), intent(inout) :: state
Supported values for the <value argument> are:
integer(ESMF_KIND_I4), intent(in) :: value
integer(ESMF_KIND_I8), intent(in) :: value
real (ESMF_KIND_R4), intent(in) :: value
real (ESMF_KIND_R8), intent(in) :: value
logical, intent(in) :: value
character (len = *), intent(in), :: value

The arguments are:

<object>
An ESMF object
name
The name of the Attribute to set
<value argument>
The value of the Attribute to set
[convention]
The convention of the Attribute package
[purpose]
The purpose of the Attribute package
[rc]
Return code; equals ESMF_SUCCESS if there are no errors

31.6.22 ESMF_AttributeSet - Set an Attribute


INTERFACE:

   subroutine ESMF_AttributeSet(<object>, name, <valueList argument>, &
   convention, purpose, 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
   integer, intent(in), optional :: itemCount
   integer, intent(out), optional :: rc
DESCRIPTION:

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 a convention and purpose. See Section 31.1.3 for a description of Attribute packages and their conventions, purposes, and object types.

Supported values for <object> are:

type(ESMF_Array), intent(inout) :: array
type(ESMF_ArrayBundle), intent(inout) :: arraybundle
type(ESMF_CplComp), intent(inout) :: comp
type(ESMF_GridComp), intent(inout) :: comp
type(ESMF_DistGrid), intent(inout) :: distgrid
type(ESMF_Field), intent(inout) :: field
type(ESMF_FieldBundle), intent(inout) :: fieldbundle
type(ESMF_Grid), intent(inout) :: grid
type(ESMF_State), intent(inout) :: state
Supported values for the <value argument> are:
integer(ESMF_KIND_I4), dimension(:), intent(in) :: valueList
integer(ESMF_KIND_I8), dimension(:), intent(in) :: valueList
real (ESMF_KIND_R4), dimension(:), intent(in) :: valueList
real (ESMF_KIND_R8), dimension(:), intent(in) :: valueList
logical, dimension(:), intent(in) :: valueList
character (len = *), dimension(:), intent(in), :: valueList

The arguments are:

<object>
An ESMF object
name
The name of the Attribute to set
<valueList argument>
The valueList of the Attribute to set
[convention]
The convention of the Attribute package
[purpose]
The purpose of the Attribute package
[itemCount]
The number of items in a multi-valued Attribute
[rc]
Return code; equals ESMF_SUCCESS if there are no errors

31.6.23 ESMF_AttributeUpdate - Update an Attribute hierarchy


INTERFACE:

   subroutine ESMF_AttributeUpdate(<object>, vm, rootList, rc)
ARGUMENTS:
   <object>, see below for supported values
   type(ESMF_VM), intent(in) :: vm
   integer, dimension(:), intent(in) :: rootList
   integer, intent(out), optional :: rc
DESCRIPTION:

Update an Attribute hierarchy during runtime. Supported values for <object> are:

type(ESMF_Array), intent(inout) :: array
type(ESMF_ArrayBundle), intent(inout) :: arraybundle
type(ESMF_CplComp), intent(inout) :: comp
type(ESMF_GridComp), intent(inout) :: comp
type(ESMF_Field), intent(inout) :: field
type(ESMF_FieldBundle), intent(inout) :: fieldbundle
type(ESMF_State), intent(inout) :: state

The arguments are:

<object>
An ESMF object
vm
The virtural machine over which this Attribute hierarchy should be updated
rootList
The list of ``root'' PETs that are to be used to update
[rc]
Return code; equals ESMF_SUCCESS if there are no errors

31.6.24 ESMF_AttributeWrite - Write an Attribute package


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 :: rc
DESCRIPTION:

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. See Section 31.1.3 for a description of Attribute packages and their conventions, purposes, and object types.

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:

"http://his.cuahsi.org/wofws.html"
"http://www.earthsystemcurator.org/projects/waterml.shtml"

An ESMF Use Test Case is available which showcases an example of how to write a WaterML file; please see

"http://esmf.cvs.sourceforge.net/viewvc/esmf/use_test_cases/ESMF_WaterML"
"http://esmf.cvs.sourceforge.net/viewvc/esmf/use_test_cases/README"

Supported values for <object> are:

type(ESMF_Array), intent(inout) :: array
type(ESMF_ArrayBundle), intent(inout) :: arraybundle
type(ESMF_CplComp), intent(inout) :: comp
type(ESMF_GridComp), intent(inout) :: comp
type(ESMF_Field), intent(inout) :: field
type(ESMF_FieldBundle), intent(inout) :: fieldbundle
type(ESMF_State), intent(inout) :: state

The arguments are:

<object>
An ESMF object
[convention]
The convention of the Attribute package
[purpose]
The purpose of the Attribute package
[attwriteflag]
The flag to specify which format is desired for the write, the default is tab-delimited
[rc]
Return code; equals ESMF_SUCCESS if there are no errors

NOTE: The options for attwriteflag include:

  1. ESMF_ATTWRITE_XML will write in xml format
  2. ESMF_ATTWRITE_TAB will write in tab-delimited format

32 Attachable Methods

32.1 Description

ESMF data types, such as Fields, FieldBundles, Arrays and ArrayBundles, are used to exchange data between Components through States. In the simplest scenario the producer Component or Coupler can compute the full data set required by the consumer Component. However, memory constraints or otherwise the nature of the algorithm, may require that the final calculation be performed right before the data is consumed.

ESMF provides the concept of Attachable Methods that allows a producer component to associate user defined methods with the data objects it provides. The final calculation, while defined by the producer Component, is deferred until the consumer Component requires its execution.

The current implementation of Attachable Methods is limited to the ESMF State class. States are a general container class for Fields, FieldBundles, Arrays and ArrayBundles. States provide the most general interface to Attachable Methods.

32.2 Use and Examples

The following examples demonstrate how a producer Component attaches a user defined method to a State, and how it implements the method. The attached method is then executed by the consumer Component.

32.2.1 Producer Component attaches user defined method

The producer Component attaches a user defined method to exportState during the Component's initialize method. The user defined method is attached with label finalCalculation by which it will become accessible to the consumer Component.

  subroutine init(gcomp, importState, exportState, clock, rc)
    ! arguments
    type(ESMF_GridComp):: gcomp
    type(ESMF_State):: importState, exportState
    type(ESMF_Clock):: clock
    integer, intent(out):: rc
    
    call ESMF_MethodAdd(exportState, label="finalCalculation", &
      userRoutine=finalCalc, rc=rc)

    rc = 0
  end subroutine !--------------------------------------------------------------

32.2.2 Producer Component implements user defined method

The producer Component implements the attached, user defined method finalCalc. Strict interface rules apply for the user defined method.

  subroutine finalCalc(state, rc)
    ! arguments
    type(ESMF_State):: state
    integer, intent(out):: rc

    ! access data objects in state and perform calculation
    
    print *, "dummy output from attached method "

    rc = 0
  end subroutine !--------------------------------------------------------------

32.2.3 Consumer Component executes user defined method

The consumer Component executes the user defined method on the importState.

  subroutine init(gcomp, importState, exportState, clock, rc)
    ! arguments
    type(ESMF_GridComp):: gcomp
    type(ESMF_State):: importState, exportState
    type(ESMF_Clock):: clock
    integer, intent(out):: rc
    
    integer:: userRc
    
    call ESMF_MethodExecute(importState, label="finalCalculation", &
      userRc=userRc, rc=rc)

    rc = 0
  end subroutine !--------------------------------------------------------------

32.3 Restrictions and Future Work

  1. Only States. The current implementation of Attachable Methods is limited to the ESMF State class. States are a general container class for Fields, FieldBundles, Arrays and ArrayBundles. States provide the most general interface to Attachable Methods. Dependent on future requirements, the Attachable Methods concept may be extended to other ESMF data classes as the need arises.
  2. Not reconciled. Attachable Methods are PET-local settings on a State. Currently Attachable Methods are ignored during ESMF_StateReconcile().
  3. No copy nor move. Currently Attachable Methods cannot be copied or moved between States.

32.4 Class API

32.4.1 ESMF_MethodAdd - Attach user method


INTERFACE:

   ! Private name; call using ESMF_MethodAdd()
   subroutine ESMF_MethodAdd(state, label, userRoutine, rc)
ARGUMENTS:
     type(ESMF_State)                        :: state
     character(len=*), intent(in)            :: label
     interface
       subroutine userRoutine(state, rc)
         use ESMF_StateMod
         implicit none
         type(ESMF_State)            :: state        ! must not be optional
         integer, intent(out)        :: rc           ! must not be optional
       end subroutine
     end interface
     integer,          intent(out), optional :: rc
DESCRIPTION:

Attach userRoutine.

The arguments are:

state
The ESMF_State to print.
label
Label of method.
userRoutine
The user-supplied subroutine to be associated with the label.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

32.4.2 ESMF_MethodAdd - Attach user method, located in shared object


INTERFACE:

   ! Private name; call using ESMF_MethodAdd()
   subroutine ESMF_MethodAddShObj(state, label, userRoutine, sharedObj, rc)
ARGUMENTS:
     type(ESMF_State)                        :: state
     character(len=*), intent(in)            :: label
     character(len=*), intent(in)            :: userRoutine
     character(len=*), intent(in),  optional :: sharedObj
     integer,          intent(out), optional :: rc
DESCRIPTION:

Attach userRoutine.

The arguments are:

state
The ESMF_State to print.
label
Label of method.
userRoutine
Name of user-supplied subroutine to be associated with the label.
[sharedObj]
Name of shared object that contains userRoutine. If the sharedObj argument is not provided the executable itself will be searched for userRoutine.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

32.4.3 ESMF_MethodExecute - Execute user method


INTERFACE:

   subroutine ESMF_MethodExecute(state, label, userRc, rc)
ARGUMENTS:
     type(ESMF_State)                        :: state
     character(len=*), intent(in)            :: label
     integer,          intent(out), optional :: userRc
     integer,          intent(out), optional :: rc
DESCRIPTION:

Execute attached method.

The arguments are:

state
The ESMF_State to print.
label
Label of method.
[userRc]
Return code set by attached method before returning.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

32.4.4 ESMF_MethodRemove - Remove user method


INTERFACE:

   subroutine ESMF_MethodRemove(state, label, rc)
ARGUMENTS:
     type(ESMF_State)                        :: state
     character(len=*), intent(in)            :: label
     integer,          intent(out), optional :: rc
DESCRIPTION:

Remove attached method.

The arguments are:

state
The ESMF_State to print.
label
Label of method.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

33 Time Manager Utility

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 types, including user-customized calendars.
Support for both concurrent and sequential modes of component execution.
Support for varying and negative time steps.

33.1 Time Manager Classes

There are five ESMF classes that represent time concepts:

\includegraphics[]{TimeMgr_desc}

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.

33.2 Calendar

An ESMF Calendar can be queried for seconds per day, days per month and days per year. The flexible definition of Calendars allows them to be defined for planetary bodies other than Earth. The set of supported calendars includes:
Gregorian
The standard Gregorian calendar.
no-leap
The Gregorian calendar with no leap years.
Julian
The standard Julian date calendar.
Julian Day
The standard Julian days calendar.
Modified Julian Day
The Modified Julian days calendar.
360-day
A 30-day-per-month, 12-month-per-year calendar.
no calendar
Tracks only elapsed model time in hours, minutes, seconds.
See Section 34.1 for more details on supported standard calendars, and how to create a customized ESMF Calendar.

33.3 Time Instants and TimeIntervals

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 35.1 and 36.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 33.4.

33.4 Clocks and Alarms

Although it is possible to repeatedly step a Time forward by a TimeInterval using arithmetic on these basic types, it is useful to identify a higher-level concept to represent this function. We refer to this capability as a Clock, and include in its required features the ability to store the start and stop times of a model run, to check when time advancement should cease, and to query the value of quantities such as the current time and the time at the previous time step. The Time Manager includes a class with methods that return a true value when a periodic or unique event has taken place; we refer to these as Alarms. Applications may contain temporary or multiple Clocks and Alarms. Sections 37.1 and 38.1 describe the use of Clocks and Alarms in detail.


Table 2: Specifiers for Times and TimeIntervals
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 $ +
\frac{{\rm sN}}{{\rm sD}}$, 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 $ +
\frac{{\rm sN}}{{\rm sD}}$, where s is seconds and s, sN, and sD are integers.

33.5 Design and Implementation Notes

  1. Base TimeIntervals and Times on the same integer representation. It is useful to allow both TimeIntervals and Times to inherit from a single class, BaseTime. In C++, this can be implemented by using inheritance. In Fortran, it can be implemented by having the derived types TimeIntervals and Times contain a derived type BaseTime. In both cases, the BaseTime class can be made private and invisible to the user.

    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 33.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.

  2. The Time class depends on a calendar. The Time class contains an internal Calendar class. Upon demand by a user, the results of an increment or decrement operation are converted to user units, which may be calendar-dependent, via methods obtained from their internal Calendar.

33.6 Object Model

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.

\includegraphics[]{TimeMgr_obj}

34 Calendar Class

34.1 Description

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 [29] and [22].

34.2 Calendar Options


34.2.1 ESMF_CalendarType

DESCRIPTION:
Supported calendar types.

Valid values are:

ESMF_CAL_360DAY
Valid range: machine limits
In the 360-day calendar, there are 12 months, each of which has 30 days. Like the no-leap calendar, this is a simple approximation to the Gregorian calendar sometimes used by modelers.

ESMF_CAL_CUSTOM
Valid range: machine limits
The user can set calendar parameters in the generic calendar.

ESMF_CAL_GREGORIAN
Valid range: 3/1/4801 BC to 10/29/292,277,019,914
The Gregorian calendar is the calendar currently in use throughout Western countries. Named after Pope Gregory XIII, it is a minor correction to the older Julian calendar. In the Gregorian calendar every fourth year is a leap year in which February has 29 and not 28 days; however, years divisible by 100 are not leap years unless they are also divisible by 400. As in the Julian calendar, days begin at midnight.

ESMF_CAL_JULIAN
Valid range: 3/1/4713 BC to 4/24/292,271,018,333
The Julian calendar was introduced by Julius Caesar in 46 B.C., and reached its final form in 4 A.D. The Julian calendar differs from the Gregorian only in the determination of leap years, lacking the correction for years divisible by 100 and 400 in the Gregorian calendar. In the Julian calendar, any year is a leap year if divisible by 4. Days are considered to begin at midnight.

ESMF_CAL_JULIANDAY
Valid range: +/- 1x10$^{14}$
Julian days simply enumerate the days and fraction of a day which have elapsed since the start of the Julian era, defined as beginning at noon on Monday, 1st January of year 4713 B.C. in the Julian calendar. Julian days, unlike the dates in the Julian and Gregorian calendars, begin at noon.

ESMF_CAL_MODJULIANDAY
Valid range: +/- 1x10$^{14}$
The Modified Julian Day (MJD) was introduced by space scientists in the late 1950's. It is defined as an offset from the Julian Day (JD):

MJD = JD - 2400000.5

The half day is subtracted so that the day starts at midnight.

ESMF_CAL_NOCALENDAR
Valid range: machine limits
The no-calendar option simply tracks the elapsed model time in seconds.

ESMF_CAL_NOLEAP
Valid range: machine limits
The no-leap calendar is the Gregorian calendar with no leap years - February is always assumed to have 28 days. Modelers sometimes use this calendar as a simple, close approximation to the Gregorian calendar.

34.3 Use and Examples

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 types
!-----------------------------------------------------------------------------

      ! ESMF Framework module
      use ESMF_Mod
      implicit none

      ! instantiate calendars
      type(ESMF_Calendar) :: gregorianCalendar
      type(ESMF_Calendar) :: julianDayCalendar

      ! local variables for Get methods
      integer(ESMF_KIND_I8) :: dl
      type(ESMF_Time) :: time

      ! return code
      integer:: rc

      ! initialize ESMF framework
      call ESMF_Initialize(rc=rc)

34.3.1 Calendar Creation

This example shows how to create two ESMF_Calendars.

      ! create a Gregorian calendar
      gregorianCalendar = ESMF_CalendarCreate("Gregorian", &
                                              ESMF_CAL_GREGORIAN, rc)

      ! create a Julian Day calendar
      julianDayCalendar = ESMF_CalendarCreate("JulianDay", &
                                              ESMF_CAL_JULIANDAY, rc)

34.3.2 Calendar Comparison

This example shows how to compare an ESMF_Calendar with a known calendar type.

      ! compare calendar type against a known type
      if (gregorianCalendar == ESMF_CAL_GREGORIAN) then
          print *, "gregorianCalendar is of type ESMF_CAL_GREGORIAN."
      else
          print *, "gregorianCalendar is not of type ESMF_CAL_GREGORIAN."
      end if

34.3.3 Time Conversion Between Calendars

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."

34.3.4 Calendar Destruction

This example shows how to destroy two ESMF_Calendars.

      call ESMF_CalendarDestroy(julianDayCalendar, rc)

      call ESMF_CalendarDestroy(gregorianCalendar, rc)

      ! finalize ESMF framework
      call ESMF_Finalize(rc=rc)

      end program ESMF_CalendarEx

34.4 Restrictions and Future Work

  1. Months per year set to 12. Due to the requirement of only Earth modeling, the number of months per year is hard-coded at 12. However, for easy modification, this is implemented via a Fortran parameter and a C preprocessor #define.

34.5 Class API

34.5.1 ESMF_CalendarOperator(==) - Test if Calendar 1 is equal to Calendar 2


INTERFACE:

       interface operator(==)
       if (calendar1 == calendar2) then ... endif
                    OR
       result = (calendar1 == calendar2)
RETURN VALUE:
       logical :: result
ARGUMENTS:
       type(ESMF_Calendar), intent(in) :: calendar1
       type(ESMF_Calendar), intent(in) :: calendar2
DESCRIPTION:

Overloads the (==) operator for the ESMF_Calendar class. Compare two calendar objects for equality; return true if equal, false otherwise. Comparison is based on the calendar type.

The arguments are:

calendar1
The first ESMF_Calendar in comparison.
calendar2
The second ESMF_Calendar in comparison.

34.5.2 ESMF_CalendarOperator(==) - Test if Calendar Type 1 is equal to Calendar Type 2


INTERFACE:

       interface operator(==)
       if (calendartype1 == calendartype2) then ... endif
                    OR
       result = (calendartype1 == calendartype2)
RETURN VALUE:
       logical :: result
ARGUMENTS:
       type(ESMF_CalendarType), intent(in) :: calendartype1
       type(ESMF_CalendarType), intent(in) :: calendartype2
DESCRIPTION:

Overloads the (==) operator for the ESMF_Calendar class. Compare two calendar types for equality; return true if equal, false otherwise.

The arguments are:

calendartype1
The first ESMF_CalendarType in comparison.
calendartype2
The second ESMF_CalendarType in comparison.

34.5.3 ESMF_CalendarOperator(==) - Test if Calendar is equal to Calendar Type


INTERFACE:

       interface operator(==)
       if (calendar == calendartype) then ... endif
                    OR
       result = (calendar == calendartype)
RETURN VALUE:
       logical :: result
ARGUMENTS:
       type(ESMF_Calendar),     intent(in) :: calendar
       type(ESMF_CalendarType), intent(in) :: calendartype
DESCRIPTION:

Overloads the (==) operator for the ESMF_Calendar class. Compare a calendar object's type with a given calendar type for equality; return true if equal, false otherwise.

The arguments are:

calendar
The ESMF_Calendar in comparison.
calendartype
The ESMF_CalendarType in comparison.

34.5.4 ESMF_CalendarOperator(==) - Test if Calendar Type is equal to Calendar


INTERFACE:

       interface operator(==)
       if (calendartype == calendar) then ... endif
                    OR
       result = (calendartype == calendar)
RETURN VALUE:
       logical :: result
ARGUMENTS:
       type(ESMF_CalendarType), intent(in) :: calendartype
       type(ESMF_Calendar),     intent(in) :: calendar
DESCRIPTION:

Overloads the (==) operator for the ESMF_Calendar class. Compare a calendar type with a given calendar object's type for equality; return true if equal, false otherwise.

The arguments are:

calendartype
The ESMF_CalendarType in comparison.
calendar
The ESMF_Calendar in comparison.

34.5.5 ESMF_CalendarOperator(/=) - Test if Calendar 1 is not equal to Calendar 2


INTERFACE:

       interface operator(/=)
       if (calendar1 /= calendar2) then ... endif
                    OR
       result = (calendar1 /= calendar2)
RETURN VALUE:
       logical :: result
ARGUMENTS:
       type(ESMF_Calendar), intent(in) :: calendar1
       type(ESMF_Calendar), intent(in) :: calendar2
DESCRIPTION:

Overloads the (/=) operator for the ESMF_Calendar class. Compare two calendar objects for inequality; return true if not equal, false otherwise. Comparison is based on the calendar type.

The arguments are:

calendar1
The first ESMF_Calendar in comparison.
calendar2
The second ESMF_Calendar in comparison.

34.5.6 ESMF_CalendarOperator(/=) - Test if Calendar Type 1 is not equal to Calendar Type 2


INTERFACE:

       interface operator(/=)
       if (calendartype1 /= calendartype2) then ... endif
                    OR
       result = (calendartype1 /= calendartype2)
RETURN VALUE:
       logical :: result
ARGUMENTS:
       type(ESMF_CalendarType), intent(in) :: calendartype1
       type(ESMF_CalendarType), intent(in) :: calendartype2
DESCRIPTION:

Overloads the (/=) operator for the ESMF_Calendar class. Compare two calendar types for inequality; return true if not equal, false otherwise.

The arguments are:

calendartype1
The first ESMF_CalendarType in comparison.
calendartype2
The second ESMF_CalendarType in comparison.

34.5.7 ESMF_CalendarOperator(/=) - Test if Calendar is not equal to Calendar Type


INTERFACE:

       interface operator(/=)
       if (calendar /= calendartype) then ... endif
                    OR
       result = (calendar /= calendartype)
RETURN VALUE:
       logical :: result
ARGUMENTS:
       type(ESMF_Calendar),     intent(in) :: calendar
       type(ESMF_CalendarType), intent(in) :: calendartype
DESCRIPTION:

Overloads the (/=) operator for the ESMF_Calendar class. Compare a calendar object's type with a given calendar type for inequality; return true if equal, false otherwise.

The arguments are:

calendar
The ESMF_Calendar in comparison.
calendartype
The ESMF_CalendarType in comparison.

34.5.8 ESMF_CalendarOperator(/=) - Test if Calendar Type is not equal to Calendar


INTERFACE:

       interface operator(/=)
       if (calendartype /= calendar) then ... endif
                    OR
       result = (calendartype /= calendar)
RETURN VALUE:
       logical :: result
ARGUMENTS:
       type(ESMF_CalendarType), intent(in) :: calendartype
       type(ESMF_Calendar),     intent(in) :: calendar
DESCRIPTION:

Overloads the (/=) operator for the ESMF_Calendar class. Compare a calendar type with a given calendar object's type for inequality; return true if equal, false otherwise.

The arguments are:

calendartype
The ESMF_CalendarType in comparison.
calendar
The ESMF_Calendar in comparison.

34.5.9 ESMF_CalendarCreate - Create a new ESMF Calendar of built-in type


INTERFACE:

       ! Private name; call using ESMF_CalendarCreate()
       function ESMF_CalendarCreateBuiltIn(name, calendartype, rc)
RETURN VALUE:
       type(ESMF_Calendar) :: ESMF_CalendarCreateBuiltIn
ARGUMENTS:
       character (len=*),       intent(in),  optional :: name
       type(ESMF_CalendarType), intent(in)            :: calendartype
       integer,                 intent(out), optional :: rc
DESCRIPTION:

Creates and sets a calendar to the given built-in ESMF_CalendarType.

This is a private method; invoke via the public overloaded entry point ESMF_CalendarCreate().

The arguments are:

[name]
The name for the newly created calendar. If not specified, a default unique name will be generated: "CalendarNNN" where NNN is a unique sequence number from 001 to 999.
calendartype
The built-in ESMF_CalendarType. Valid values are: ESMF_CAL_360DAY, ESMF_CAL_GREGORIAN, ESMF_CAL_JULIAN, ESMF_CAL_JULIANDAY, ESMF_CAL_MODJULIANDAY, ESMF_CAL_NOCALENDAR, and ESMF_CAL_NOLEAP. See Section 34.2 for a description of each calendar type.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

34.5.10 ESMF_CalendarCreate - Create a copy of an ESMF Calendar


INTERFACE:

       ! Private name; call using ESMF_CalendarCreate()
       function ESMF_CalendarCreateCopy(calendar, rc)
RETURN VALUE:
       type(ESMF_Calendar) :: ESMF_CalendarCreateCopy
ARGUMENTS:
       type(ESMF_Calendar), intent(in)            :: calendar
       integer,             intent(out), optional :: rc
DESCRIPTION:

Creates a copy of a given ESMF_Calendar.

This is a private method; invoke via the public overloaded entry point ESMF_CalendarCreate().

The arguments are:

calendar
The ESMF_Calendar to copy.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

34.5.11 ESMF_CalendarCreate - Create a new custom ESMF Calendar


INTERFACE:

       ! Private name; call using ESMF_CalendarCreate()
       function ESMF_CalendarCreateCustom(name, daysPerMonth, secondsPerDay, &
                                          daysPerYear, daysPerYearDn, &
                                          daysPerYearDd, rc)
RETURN VALUE:
       type(ESMF_Calendar) :: ESMF_CalendarCreateCustom
ARGUMENTS:
       character (len=*),     intent(in),  optional :: name
       integer, dimension(:), intent(in),  optional :: daysPerMonth
       integer(ESMF_KIND_I4), intent(in),  optional :: secondsPerDay
       integer(ESMF_KIND_I4), intent(in),  optional :: daysPerYear   ! not implemented
       integer(ESMF_KIND_I4), intent(in),  optional :: daysPerYearDn ! not implemented
       integer(ESMF_KIND_I4), intent(in),  optional :: daysPerYearDd ! not implemented
       integer,               intent(out), optional :: rc
DESCRIPTION:

Creates a custom ESMF_Calendar and sets its properties.

This is a private method; invoke via the public overloaded entry point ESMF_CalendarCreate().

The arguments are:

[name]
The name for the newly created calendar. If not specified, a default unique name will be generated: "CalendarNNN" where NNN is a unique sequence number from 001 to 999.
[daysPerMonth]
Integer array of days per month, for each month of the year. The number of months per year is variable and taken from the size of the array. If unspecified, months per year = 0, with the days array undefined.
[secondsPerDay]
Integer number of seconds per day. Defaults to 86400 if not specified.
[daysPerYear]
Integer number of days per year. Use with daysPerYearDn and daysPerYearDd (see below) to specify a days-per-year calendar for any planetary body. Default = 0. (Not implemented yet).
[daysPerYearDn]
Integer numerator portion of fractional number of days per year (daysPerYearDn/daysPerYearDd). Use with daysPerYear (see above) and daysPerYearDd (see below) to specify a days-per-year calendar for any planetary body. Default = 0. (Not implemented yet).
[daysPerYearDd]
Integer denominator portion of fractional number of days per year (daysPerYearDn/daysPerYearDd). Use with daysPerYear and daysPerYearDn (see above) to specify a days-per-year calendar for any planetary body. Default = 1. (Not implemented yet).
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

34.5.12 ESMF_CalendarDestroy - Free resources associated with a Calendar


INTERFACE:

       subroutine ESMF_CalendarDestroy(calendar, rc)
ARGUMENTS:
       type(ESMF_Calendar)            :: calendar
       integer, intent(out), optional :: rc
DESCRIPTION:

Releases all resources associated with this ESMF_Calendar.

The arguments are:

calendar
Destroy contents of this ESMF_Calendar.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

34.5.13 ESMF_CalendarGet - Get Calendar properties


INTERFACE:

       subroutine ESMF_CalendarGet(calendar, name, calendartype, &
                                   daysPerMonth, monthsPerYear, &
                                   secondsPerDay, secondsPerYear, &
                                   daysPerYear, &
                                   daysPerYearDn, daysPerYearDd, rc)
ARGUMENTS:
       type(ESMF_Calendar),     intent(inout)         :: calendar
       character (len=*),       intent(out), optional :: name
       type(ESMF_CalendarType), intent(out), optional :: calendartype
       integer, dimension(:),   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   ! not implemented
       integer(ESMF_KIND_I4),   intent(out), optional :: daysPerYearDn ! not implemented
       integer(ESMF_KIND_I4),   intent(out), optional :: daysPerYearDd ! not implemented
       integer,                 intent(out), optional :: rc
DESCRIPTION:

Gets one or more of an ESMF_Calendar's properties.

The arguments are:

calendar
The object instance to query.
[name]
The name of this calendar.
[calendartype]
The CalendarType ESMF_CAL_GREGORIAN, ESMF_CAL_JULIAN, etc.
[daysPerMonth]
Integer array of days per month, for each month of the year.
[monthsPerYear]
Integer number of months per year; the size of the daysPerMonth array.
[secondsPerDay]
Integer number of seconds per day.
[secondsPerYear]
Integer number of seconds per year.
[daysPerYear]
Integer number of days per year. For calendars with intercalations, daysPerYear is the number of days for years without an intercalation. For other calendars, it is the number of days in every year. (Not implemented yet).
[daysPerYearDn]
Integer fractional number of days per year (numerator). For calendars with intercalations, daysPerYearDn/daysPerYearDd is the average fractional number of days per year (e.g. 25/100 for Julian 4-year intercalation). For other calendars, it is zero. (Not implemented yet).
[daysPerYearDd]
Integer fractional number of days per year (denominator). See daysPerYearDn above. (Not implemented yet).
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

34.5.14 ESMF_CalendarIsLeapYear - Determine if given year is a leap year


INTERFACE:

       ! Private name; call using ESMF_CalendarIsLeapYear()
       function ESMF_CalendarIsLeapYearI4(calendar, yy, rc)
RETURN VALUE:
       logical :: ESMF_CalendarIsLeapYearI4
ARGUMENTS:
       type(ESMF_Calendar),   intent(inout)         :: calendar
       integer(ESMF_KIND_I4), intent(in)            :: yy
       integer,               intent(out), optional :: rc
DESCRIPTION:

Returns true if the given year is a leap year within the given calendar, and false otherwise. See also ESMF_TimeIsLeapYear().

This is a private method; invoke via the public overloaded entry point ESMF_CalendarIsLeapYear().

The arguments are:

calendar
ESMF_Calendar to determine leap year within.
yy
Year to check for leap year.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

34.5.15 ESMF_CalendarIsLeapYear - Determine if given year is a leap year


INTERFACE:

       ! Private name; call using ESMF_CalendarIsLeapYear()
       function ESMF_CalendarIsLeapYearI8(calendar, yy_i8, rc)
RETURN VALUE:
       logical :: ESMF_CalendarIsLeapYearI8
ARGUMENTS:
       type(ESMF_Calendar),   intent(inout)         :: calendar
       integer(ESMF_KIND_I8), intent(in)            :: yy_i8
       integer,               intent(out), optional :: rc
DESCRIPTION:

Returns true if the given year is a leap year within the given calendar, and false otherwise. See also ESMF_TimeIsLeapYear().

This is a private method; invoke via the public overloaded entry point ESMF_CalendarIsLeapYear().

The arguments are:

calendar
ESMF_Calendar to determine leap year within.
yy_i8
Year to check for leap year.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

34.5.16 ESMF_CalendarPrint - Print the contents of a Calendar


INTERFACE:

       subroutine ESMF_CalendarPrint(calendar, options, rc)
ARGUMENTS:
       type(ESMF_Calendar), intent(inout)         :: calendar
       character (len=*),   intent(in),  optional :: options
       integer,             intent(out), optional :: rc
DESCRIPTION:

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.

Note: Many ESMF_<class>Print methods are implemented in C++. On some platforms/compilers there is a potential issue with interleaving Fortran and C++ output to stdout such that it doesn't appear in the expected order. If this occurs, the ESMF_IOUnitFlush() method may be used on unit 6 to get coherent output.

The arguments are:

calendar
ESMF_Calendar to be printed out.
[options]
Print options. If none specified, prints all calendar property values.
"calendartype" - print the calendar's type (e.g. ESMF_CAL_GREGORIAN).
"daysPerMonth" - print the array of number of days for each month.
"daysPerYear" - print the number of days per year (integer and fractional parts).
"monthsPerYear" - print the number of months per year.
"name" - print the calendar's name.
"secondsPerDay" - print the number of seconds in a day.
"secondsPerYear" - print the number of seconds in a year.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

34.5.17 ESMF_CalendarSet - Set a Calendar to a built-in type


INTERFACE:

       ! Private name; call using ESMF_CalendarSet()
       subroutine ESMF_CalendarSetBuiltIn(calendar, name, calendartype, rc)
ARGUMENTS:
       type(ESMF_Calendar),     intent(inout)         :: calendar
       character (len=*),       intent(in),  optional :: name
       type(ESMF_CalendarType), intent(in)            :: calendartype
       integer,                 intent(out), optional :: rc
DESCRIPTION:

Sets calendar to the given built-in ESMF_CalendarType.

This is a private method; invoke via the public overloaded entry point ESMF_CalendarSet().

The arguments are:

calendar
The object instance to initialize.
[name]
The new name for this calendar.
calendartype
The built-in CalendarType. Valid values are: ESMF_CAL_360DAY, ESMF_CAL_GREGORIAN, ESMF_CAL_JULIAN, ESMF_CAL_JULIANDAY, ESMF_CAL_MODJULIANDAY, ESMF_CAL_NOCALENDAR, and ESMF_CAL_NOLEAP. See Section 34.2 for a description of each calendar type.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

34.5.18 ESMF_CalendarSet - Set properties of a custom Calendar


INTERFACE:

       ! Private name; call using ESMF_CalendarSet()
       subroutine ESMF_CalendarSetCustom(calendar, name, daysPerMonth, &
                                         secondsPerDay, &
                                         daysPerYear, daysPerYearDn, &
                                         daysPerYearDd, rc)
ARGUMENTS:
       type(ESMF_Calendar),   intent(inout)         :: calendar
       character (len=*),     intent(in),  optional :: name
       integer, dimension(:), intent(in),  optional :: daysPerMonth
       integer(ESMF_KIND_I4), intent(in),  optional :: secondsPerDay
       integer(ESMF_KIND_I4), intent(in),  optional :: daysPerYear   ! not implemented
       integer(ESMF_KIND_I4), intent(in),  optional :: daysPerYearDn ! not implemented
       integer(ESMF_KIND_I4), intent(in),  optional :: daysPerYearDd ! not implemented
       integer,               intent(out), optional :: rc
DESCRIPTION:

Sets properties in a custom ESMF_Calendar.

This is a private method; invoke via the public overloaded entry point ESMF_CalendarSet().

The arguments are:

calendar
The object instance to initialize.
[name]
The new name for this calendar.
[daysPerMonth]
Integer array of days per month, for each month of the year. The number of months per year is variable and taken from the size of the array. If unspecified, months per year = 0, with the days array undefined.
[secondsPerDay]
Integer number of seconds per day. Defaults to 86400 if not specified.
[daysPerYear]
Integer number of days per year. Use with daysPerYearDn and daysPerYearDd (see below) to specify a days-per-year calendar for any planetary body. Default = 0. (Not implemented yet).
[daysPerYearDn]
Integer numerator portion of fractional number of days per year (daysPerYearDn/daysPerYearDd). Use with daysPerYear (see above) and daysPerYearDd (see below) to specify a days-per-year calendar for any planetary body. Default = 0. (Not implemented yet).
[daysPerYearDd]
Integer denominator portion of fractional number of days per year (daysPerYearDn/daysPerYearDd). Use with daysPerYear and daysPerYearDn (see above) to specify a days-per-year calendar for any planetary body. Default = 1. (Not implemented yet).
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

34.5.19 ESMF_CalendarSetDefault - Set the default Calendar type


INTERFACE:

       ! Private name; call using ESMF_CalendarSetDefault()
       subroutine ESMF_CalendarSetDefaultType(calendartype, rc)
ARGUMENTS:
       type(ESMF_CalendarType), intent(in)            :: calendartype
       integer,                 intent(out), optional :: rc
DESCRIPTION:

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.

This is a private method; invoke via the public overloaded entry point ESMF_CalendarSetDefault().

The arguments are:

calendartype
The calendar type to be the default.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

34.5.20 ESMF_CalendarSetDefault - Set the default Calendar


INTERFACE:

       ! Private name; call using ESMF_CalendarSetDefault()
       subroutine ESMF_CalendarSetDefaultCal(calendar, rc)
ARGUMENTS:
       type(ESMF_Calendar),     intent(inout)         :: calendar
       integer,                 intent(out), optional :: rc
DESCRIPTION:

Sets the default calendar to the one given. Subsequent Time Manager operations requiring a calendar where one isn't specified will use this calendar.

This is a private method; invoke via the public overloaded entry point ESMF_CalendarSetDefault().

The arguments are:

calendar
The object instance to be the default.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

34.5.21 ESMF_CalendarValidate - Validate a Calendar's properties


INTERFACE:

       subroutine ESMF_CalendarValidate(calendar, options, rc)
ARGUMENTS:
       type(ESMF_Calendar), intent(inout)         :: calendar
       character (len=*),   intent(in),  optional :: options
       integer,             intent(out), optional :: rc
DESCRIPTION:

Checks whether a calendar is valid. Must be one of the defined calendar types. daysPerMonth, daysPerYear, secondsPerDay must all be greater than or equal to zero.

The arguments are:

calendar
ESMF_Calendar to be validated.
[options]
Validation options are not yet supported.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

35 Time Class

35.1 Description

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 33.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 [19].

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 34.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.

35.2 Use and Examples

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
!-----------------------------------------------------------------------------

      ! ESMF Framework module
      use ESMF_Mod
      implicit none

      ! instantiate two times
      type(ESMF_Time) :: time1, time2

      ! 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(defaultCalendar=ESMF_CAL_GREGORIAN, rc=rc)

35.2.1 Time Initialization

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, "string", rc)

35.2.2 Time Increment

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, "string", 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

35.2.3 Time Comparison

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

35.3 Restrictions and Future Work

  1. Limits on size and resolution of Time. The limits on the size and resolution of the time representation are based on the 64-bit integer types used. For seconds, a signed 64-bit integer will have a range of +/- $2^{63}$-1, or +/- 9,223,372,036,854,775,807. This corresponds to a maximum size of +/- ($2^{63}$-1)/(86400 * 365.25) or +/- 292,271,023,045 years.

    For fractional seconds, a signed 64-bit integer will handle a resolution of +/- $2^{31}$-1, or +/- 9,223,372,036,854,775,807 parts of a second.

35.4 Class API

35.4.1 ESMF_TimeOperator(+) - Increment a Time by a TimeInterval


INTERFACE:

       interface operator(+)
       time2 = time1 + timeinterval
RETURN VALUE:
       type(ESMF_Time) :: time2
ARGUMENTS:
       type(ESMF_Time),         intent(in) :: time1
       type(ESMF_TimeInterval), intent(in) :: timeinterval
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:

time1
The ESMF_Time to increment.
timeinterval
The ESMF_TimeInterval to add to the given ESMF_Time.

35.4.2 ESMF_TimeOperator(-) - Decrement a Time by a TimeInterval


INTERFACE:

       interface operator(-)
       time2 = time1 - timeinterval
RETURN VALUE:
       type(ESMF_Time) :: time2
ARGUMENTS:
       type(ESMF_Time),         intent(in) :: time1
       type(ESMF_TimeInterval), intent(in) :: timeinterval
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:

time1
The ESMF_Time to decrement.
timeinterval
The ESMF_TimeInterval to subtract from the given ESMF_Time.

35.4.3 ESMF_TimeOperator(-) - Return the difference between two Times


INTERFACE:

       interface operator(-)
       time3 = time1 - time2
RETURN VALUE:
       type(ESMF_Time) :: time3
ARGUMENTS:
       type(ESMF_Time),         intent(in) :: time1
       type(ESMF_Time),         intent(in) :: time2
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:

time1
The first ESMF_Time in comparison.
time2
The second ESMF_Time in comparison.

35.4.4 ESMF_TimeOperator(==) - Test if Time 1 is equal to Time 2


INTERFACE:

       interface operator(==)
       if (time1 == time2) then ... endif
                    OR
       result = (time1 == time2)
RETURN VALUE:
       logical :: result
ARGUMENTS:
       type(ESMF_Time), intent(in) :: time1
       type(ESMF_Time), intent(in) :: time2
DESCRIPTION:

Overloads the (==) operator for the ESMF_Time class to return true if time1 and time2 are equal, and false otherwise.

The arguments are:

time1
First ESMF_Time in comparison.
time2
Second ESMF_Time in comparison.

35.4.5 ESMF_TimeOperator(/=) - Test if Time 1 is not equal to Time 2


INTERFACE:

       interface operator(/=)
       if (time1 /= time2) then ... endif
                    OR
       result = (time1 /= time2)
RETURN VALUE:
       logical :: result
ARGUMENTS:
       type(ESMF_Time), intent(in) :: time1
       type(ESMF_Time), intent(in) :: time2
DESCRIPTION:

Overloads the (/=) operator for the ESMF_Time class to return true if time1 and time2 are not equal, and false otherwise.

The arguments are:

time1
First ESMF_Time in comparison.
time2
Second ESMF_Time in comparison.

35.4.6 ESMF_TimeOperator(<) - Test if Time 1 is less than Time 2


INTERFACE:

       interface operator(<)
       if (time1 < time2) then ... endif
                    OR
       result = (time1 < time2)
RETURN VALUE:
       logical :: result
ARGUMENTS:
       type(ESMF_Time), intent(in) :: time1
       type(ESMF_Time), intent(in) :: time2
DESCRIPTION:

Overloads the (<) operator for the ESMF_Time class to return true if time1 is less than time2, and false otherwise.

The arguments are:

time1
First ESMF_Time in comparison.
time2
Second ESMF_Time in comparison.

35.4.7 ESMF_TimeOperator(<=) - Test if Time 1 is less than or equal to Time 2


INTERFACE:

       interface operator(<=)
       if (time1 <= time2) then ... endif
                    OR
       result = (time1 <= time2)
RETURN VALUE:
       logical :: result
ARGUMENTS:
       type(ESMF_Time), intent(in) :: time1
       type(ESMF_Time), intent(in) :: time2
DESCRIPTION:

Overloads the (<=) operator for the ESMF_Time class to return true if time1 is less than or equal to time2, and false otherwise.

The arguments are:

time1
First ESMF_Time in comparison.
time2
Second ESMF_Time in comparison.

35.4.8 ESMF_TimeOperator(>) - Test if Time 1 is greater than Time 2


INTERFACE:

       interface operator(>)
       if (time1 > time2) then ... endif
                    OR
       result = (time1 > time2)
RETURN VALUE:
       logical :: result
ARGUMENTS:
       type(ESMF_Time), intent(in) :: time1
       type(ESMF_Time), intent(in) :: time2
DESCRIPTION:

Overloads the (>) operator for the ESMF_Time class to return true if time1 is greater than time2, and false otherwise.

The arguments are:

time1
First ESMF_Time in comparison.
time2
Second ESMF_Time in comparison.

35.4.9 ESMF_TimeOperator(>=) - Test if Time 1 is greater than or equal to Time 2


INTERFACE:

       interface operator(>=)
       if (time1 >= time2) then ... endif
                    OR
       result = (time1 >= time2)
RETURN VALUE:
       logical :: result
ARGUMENTS:
       type(ESMF_Time), intent(in) :: time1
       type(ESMF_Time), intent(in) :: time2
DESCRIPTION:

Overloads the (>=) operator for the ESMF_Time class to return true if time1 is greater than or equal to time2, and false otherwise.

The arguments are:

time1
First ESMF_Time in comparison.
time2
Second ESMF_Time in comparison.

35.4.10 ESMF_TimeGet - Get a Time value


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, calendarType, timeZone, &
                                     timeString, timeStringISOFrac, &
                                     dayOfWeek, midMonth, &
                                     dayOfYear,  dayOfYear_r8, &
                                     dayOfYear_intvl, rc)
ARGUMENTS:
       type(ESMF_Time),         intent(inout)         :: time
       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_CalendarType), intent(out), optional :: calendarType
       integer,                 intent(out), optional :: timeZone ! not implemented
       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 :: rc
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_r8, and dayOfYear_intvl 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 [19] 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 [19] 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 [19] 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 discusion 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 discusion 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:

time
The object instance to query.
[yy]
Integer year (>= 32-bit).
[yy_i8]
Integer year (large, >= 64-bit).
[mm]
Integer month.
[dd]
Integer day of the month.
[d]
Integer Julian, or Modified Julian, days (>= 32-bit).
[d_i8]
Integer Julian, or Modified Julian, days (large, >= 64-bit).
[h]
Integer hours.
[m]
Integer minutes.
[s]
Integer seconds (>= 32-bit).
[s_i8]
Integer seconds (large, >= 64-bit).
[ms]
Integer milliseconds.
[us]
Integer microseconds.
[ns]
Integer nanoseconds.
[d_r8]
Double precision days.
[h_r8]
Double precision hours.
[m_r8]
Double precision minutes.
[s_r8]
Double precision seconds.
[ms_r8]
Double precision milliseconds.
[us_r8]
Double precision microseconds.
[ns_r8]
Double precision nanoseconds.
[sN]
Integer numerator of fractional seconds (sN/sD).
[sN_i8]
Integer numerator of fractional seconds (sN_i8/sD_i8) (large, >= 64-bit).
[sD]
Integer denominator of fractional seconds (sN/sD).
[sD_i8]
Integer denominator of fractional seconds (sN_i8/sD_i8) (large, >= 64-bit).
[calendar]
Associated Calendar.
[calendarType]
Associated CalendarType.
[timeZone]
Associated timezone (hours offset from UCT, e.g. EST = -5). (Not implemented yet).
[timeString]
Convert time value to format string YYYY-MM-DDThh:mm:ss[:n/d], where n/d is numerator/denominator of any fractional seconds and all other units are in ISO 8601 format. See [19] and  [2]. See also method ESMF_TimePrint().
[timeStringISOFrac]
Convert time value to strict ISO 8601 format string YYYY-MM-DDThh:mm:ss[.f], where f is decimal form of any fractional seconds. See [19] and [2]. See also method ESMF_TimePrint().
[dayOfWeek]
The time instant's day of the week [1-7].
[MidMonth]
The given time instant's middle-of-the-month time instant.
[dayOfYear]
The ESMF_Time instant's integer day of the year. [1-366] for Gregorian and Julian calendars, [1-365] for No-Leap calendar. [1-360] for 360-Day calendar. User-defined range for Custom calendar.
[dayOfYear_r8]
The ESMF_Time instant's floating point day of the year. [1.x-366.x] for Gregorian and Julian calendars, [1.x-365.x] for No-Leap calendar. [1.x-360.x] for 360-Day calendar. User-defined range for Custom calendar.
[dayOfYear_intvl]
The ESMF_Time instant's day of the year as an ESMF_TimeInterval.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

35.4.11 ESMF_TimeIsLeapYear - Determine if a Time is in a leap year


INTERFACE:

       function ESMF_TimeIsLeapYear(time, rc)
RETURN VALUE:
       logical :: ESMF_TimeIsLeapYear
ARGUMENTS:
       type(ESMF_Time), intent(inout)         :: time
       integer,         intent(out), optional :: rc
DESCRIPTION:

Returns true if given time is in a leap year, and false otherwise. See also ESMF_CalendarIsLeapYear().

The arguments are:

time
The ESMF_Time to check for leap year.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

35.4.12 ESMF_TimeIsSameCalendar - Compare Calendars of two Times


INTERFACE:

       function ESMF_TimeIsSameCalendar(time1, time2, rc)
RETURN VALUE:
       logical :: ESMF_TimeIsSameCalendar
ARGUMENTS:
       type(ESMF_Time), intent(inout)         :: time1
       type(ESMF_Time), intent(inout)         :: time2
       integer,         intent(out), optional :: rc
DESCRIPTION:

Returns true if the Calendars in these Times are the same, false otherwise.

The arguments are:

time1
The first ESMF_Time in comparison.
time2
The second ESMF_Time in comparison.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

35.4.13 ESMF_TimePrint - Print the contents of a Time


INTERFACE:

       subroutine ESMF_TimePrint(time, options, rc)
ARGUMENTS:
       type(ESMF_Time),   intent(inout)         :: time
       character (len=*), intent(in),  optional :: options
       integer,           intent(out), optional :: rc
DESCRIPTION:

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.

Note: Many ESMF_<class>Print methods are implemented in C++. On some platforms/compilers there is a potential issue with interleaving Fortran and C++ output to stdout such that it doesn't appear in the expected order. If this occurs, the ESMF_IOUnitFlush() method may be used on unit 6 to get coherent output.

The arguments are:

time
The ESMF_Time to be printed out.
[options]
Print options. If none specified, prints all Time property values.
"string" - prints time's value in ISO 8601 format for all units through seconds. For any non-zero fractional seconds, prints in integer rational fraction form n/d. Format is YYYY-MM-DDThh:mm:ss[:n/d], where [:n/d] is the integer numerator and denominator of the fractional seconds value, if present. See [19] and  [2]. See also method ESMF_TimeGet(..., timeString= , ...)
"string isofrac" - prints time's value in strict ISO 8601 format for all units, including any fractional seconds part. Format is YYYY-MM-DDThh:mm:ss[.f] where [.f] represents fractional seconds in decimal form, if present. See [19] and [2]. See also method ESMF_TimeGet(..., timeStringISOFrac= , ...)
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

35.4.14 ESMF_TimeSet - Initialize or set a Time


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, calendarType, &
                                     timeZone, rc)
ARGUMENTS:
       type(ESMF_Time),         intent(inout)         :: time
       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_CalendarType), intent(in),  optional :: calendarType
       integer,                 intent(in),  optional :: timeZone ! not implemented
       integer,                 intent(out), optional :: rc
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 the 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 [11] for a description of the Gregorian date-to-Julian day algorithm and [15] 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 or 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 [23] and  [1].

The Modified Julian Day, introduced by space scientists in the late 1950's, is defined as Julian-day - 2400000.5. See [32].

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), per Time Manager requirement TMG3.1. 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:

time
The object instance to initialize.
[yy]
Integer year (>= 32-bit). Default = 0
[yy_i8]
Integer year (large, >= 64-bit). Default = 0
[mm]
Integer month. Default = 1
[dd]
Integer day of the month. Default = 1
[d]
Integer Julian, or Modified Julian, days (>= 32-bit). Default = 0
[d_i8]
Integer Julian, or Modified Julian days (large, >= 64-bit). Default = 0
[h]
Integer hours. Default = 0
[m]
Integer minutes. Default = 0
[s]
Integer seconds (>= 32-bit). Default = 0
[s_i8]
Integer seconds (large, >= 64-bit). Default = 0
[ms]
Integer milliseconds. Default = 0
[us]
Integer microseconds. Default = 0
[ns]
Integer nanoseconds. Default = 0
[d_r8]
Double precision days. Default = 0.0.
[h_r8]
Double precision hours. Default = 0.0.
[m_r8]
Double precision minutes. Default = 0.0.
[s_r8]
Double precision seconds. Default = 0.0.
[ms_r8]
Double precision milliseconds. Default = 0.0.
[us_r8]
Double precision microseconds. Default = 0.0.
[ns_r8]
Double precision nanoseconds. Default = 0.0.
[sN]
Integer numerator of fractional seconds (sN/sD). Default = 0
[sN_i8]
Integer numerator of fractional seconds (sN_i8/sD_i8) (large, >= 64-bit). Default = 0
[sD]
Integer denominator of fractional seconds (sN/sD). Default = 1
[sD_i8]
Integer denominator of fractional seconds (sN_i8/sD_i8) (large, >= 64-bit). Default = 1
calendar
Associated Calendar. Defaults to calendar ESMF_CAL_NOCALENDAR or default specified in ESMF_Initialize() or ESMF_CalendarSetDefault(). Alternate to, and mutually exclusive with, calendarType below. Primarily for specifying a custom calendar type.
[calendarType]
Alternate to, and mutually exclusive with, calendar above. More convenient way of specifying a built-in calendar type.
[timeZone]
Associated timezone (hours offset from UTC, e.g. EST = -5). Default = 0 (UTC). (Not implemented yet).
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

35.4.15 ESMF_TimeSyncToRealTime - Get system real time (wall clock time)


INTERFACE:

       subroutine ESMF_TimeSyncToRealTime(time, rc)
ARGUMENTS:
       type(ESMF_Time), intent(inout) :: time
       integer, intent(out), optional :: rc
DESCRIPTION:

Gets the system real time (wall clock time), and returns it as an ESMF_Time. Accurate to the nearest second.

The arguments are:

time
The object instance to receive the real time.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

35.4.16 ESMF_TimeValidate - Validate a Time


INTERFACE:

       subroutine ESMF_TimeValidate(time, options, rc)
ARGUMENTS:
       type(ESMF_Time),   intent(inout)         :: time
       character (len=*), intent(in),  optional :: options
       integer,           intent(out), optional :: rc
DESCRIPTION:

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:

time
ESMF_Time instant to be validated.
[options]
Validation options. If none specified, validates all time property values.
"calendar" - validate only the time's calendar.
"timezone" - validate only the time's timezone.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

36 TimeInterval Class

36.1 Description

A TimeInterval represents a period between time instants. It can be either positive or negative. Like the Time interface, the TimeInterval interface is designed so that you can choose one or more options from a list of time units in order to specify a TimeInterval. See Section 33.3, Table 33.4 for the available options.

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 37.1) and Alarms (Section 38.1).

36.2 Use and Examples

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 37.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
!-----------------------------------------------------------------------------

      ! ESMF Framework module
      use ESMF_Mod
      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(defaultCalendar=ESMF_CAL_GREGORIAN, rc=rc)

36.2.1 Time Interval Initialization

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, "string", 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, "string", rc)

36.2.2 Time Interval Conversion

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."

36.2.3 Time Interval Difference

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."

36.2.4 Time Interval Multiplication

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."

36.2.5 Time Interval Comparison

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

      ! finalize ESMF framework
      call ESMF_Finalize(rc=rc)

      end program ESMF_TimeIntervalEx

36.3 Restrictions and Future Work

  1. Limits on time span. The limits on the time span that can be represented are based on the 64-bit integer types used. For seconds, a signed 64-bit integer will have a range of +/- $2^{63}$-1, or +/- 9,223,372,036,854,775,807. This corresponds to a range of +/- ($2^{63}$-1)/(86400 * 365.25) or +/- 292,271,023,045 years.

    For fractional seconds, a signed 64-bit integer will handle a resolution of +/- $2^{31}$-1, or +/- 9,223,372,036,854,775,807 parts of a second.

36.4 Class API

36.4.1 ESMF_TimeIntervalOperator(+) - Add two TimeIntervals


INTERFACE:

       interface operator(+)
       sum = timeinterval1 + timeinterval2
RETURN VALUE:
       type(ESMF_TimeInterval) :: sum
ARGUMENTS:
       type(ESMF_TimeInterval), intent(in) :: timeinterval1
       type(ESMF_TimeInterval), intent(in) :: timeinterval2
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:

timeinterval1
The augend.
timeinterval2
The addend.

36.4.2 ESMF_TimeIntervalOperator(-) - Subtract one TimeInterval from another


INTERFACE:

       interface operator(-)
       difference = timeinterval1 - timeinterval2
RETURN VALUE:
       type(ESMF_TimeInterval) :: difference
ARGUMENTS:
       type(ESMF_TimeInterval), intent(in) :: timeinterval1
       type(ESMF_TimeInterval), intent(in) :: timeinterval2
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:

timeinterval1
The minuend.
timeinterval2
The subtrahend.

36.4.3 ESMF_TimeIntervalOperator(-) - Perform unary negation on a TimeInterval


INTERFACE:

       interface operator(-)
       timeinterval = -timeinterval
RETURN VALUE:
       type(ESMF_TimeInterval) :: -timeInterval
ARGUMENTS:
       type(ESMF_TimeInterval), intent(in) :: timeinterval
DESCRIPTION:

Overloads the (-) operator for the ESMF_TimeInterval class to perform unary negation on timeinterval and return the result.

The arguments are:

timeinterval
The time interval to be negated.

36.4.4 ESMF_TimeIntervalOperator(/) - Divide two TimeIntervals, return double precision quotient


INTERFACE:

       interface operator(/)
       quotient = timeinterval1 / timeinterval2
RETURN VALUE:
       real(ESMF_KIND_R8) :: quotient
ARGUMENTS:
       type(ESMF_TimeInterval), intent(in) :: timeinterval1
       type(ESMF_TimeInterval), intent(in) :: timeinterval2
DESCRIPTION:

Overloads the (/) operator for the ESMF_TimeInterval class to return timeinterval1 divided by timeinterval2 as a double precision quotient.

The arguments are:

timeinterval1
The dividend.
timeinterval2
The divisor.

36.4.5 ESMF_TimeIntervalOperator(/) - Divide a TimeInterval by an integer, return TimeInterval quotient


INTERFACE:

       interface operator(/)
       quotient = timeinterval / divisor
RETURN VALUE:
       type(ESMF_TimeInterval) :: quotient
ARGUMENTS:
       type(ESMF_TimeInterval), intent(in) :: timeinterval
       integer(ESMF_KIND_I4),   intent(in) :: divisor
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:

timeinterval
The dividend.
divisor
Integer divisor.

36.4.6 ESMF_TimeIntervalFunction(MOD) - Divide two TimeIntervals, return TimeInterval remainder


INTERFACE:

       interface MOD
       remainder = MOD(timeinterval1, timeinterval2)
RETURN VALUE:
       type(ESMF_TimeInterval) :: remainder
ARGUMENTS:
       type(ESMF_TimeInterval), intent(in) :: timeinterval1
       type(ESMF_TimeInterval), intent(in) :: timeinterval2
DESCRIPTION:

Overloads the pre-defined MOD() function for the ESMF_TimeInterval class to return the remainder of timeinterval1 divided by timeinterval2 as an ESMF_TimeInterval.

The arguments are:

timeinterval1
The dividend.
timeinterval2
The divisor.

36.4.7 ESMF_TimeIntervalOperator(x) - Multiply a TimeInterval by an integer


INTERFACE:

       interface operator(*)
       product = timeinterval * multiplier
RETURN VALUE:
       type(ESMF_TimeInterval) :: product
ARGUMENTS:
       type(ESMF_TimeInterval), intent(in) :: timeinterval
       integer(ESMF_KIND_I4),   intent(in) :: multiplier
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.

Commutative complement to overloaded operator (*) below.

The arguments are:

timeinterval
The multiplicand.
mutliplier
The integer multiplier.

36.4.8 ESMF_TimeIntervalOperator(x) - Multiply a TimeInterval by an integer


INTERFACE:

       interface operator(*)
       product = multiplier * timeinterval
RETURN VALUE:
       type(ESMF_TimeInterval) :: product
ARGUMENTS:
       integer(ESMF_KIND_I4),   intent(in) :: multiplier
       type(ESMF_TimeInterval), intent(in) :: timeinterval
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.

Commutative complement to overloaded operator (*) above.

The arguments are:

mutliplier
The integer multiplier.
timeinterval
The multiplicand.

36.4.9 ESMF_TimeIntervalOperator(==) - Test if TimeInterval 1 is equal to TimeInterval 2


INTERFACE:

       interface operator(==)
       if (timeinterval1 == timeinterval2) then ... endif
                    OR
       result = (timeinterval1 == timeinterval2)
RETURN VALUE:
       logical :: result
ARGUMENTS:
       type(ESMF_TimeInterval), intent(in) :: timeinterval1
       type(ESMF_TimeInterval), intent(in) :: timeinterval2
DESCRIPTION:

Overloads the (==) operator for the ESMF_TimeInterval class to return true if timeinterval1 and timeinterval2 are equal, and false otherwise.

The arguments are:

timeinterval1
First ESMF_TimeInterval in comparison.
timeinterval2
Second ESMF_TimeInterval in comparison.

36.4.10 ESMF_TimeIntervalOperator(/=) - Test if TimeInterval 1 is not equal to TimeInterval 2


INTERFACE:

       interface operator(/=)
       if (timeinterval1 /= timeinterval2) then ... endif
                    OR
       result = (timeinterval1 /= timeinterval2)
RETURN VALUE:
       logical :: result
ARGUMENTS:
       type(ESMF_TimeInterval), intent(in) :: timeinterval1
       type(ESMF_TimeInterval), intent(in) :: timeinterval2
DESCRIPTION:

Overloads the (/=) operator for the ESMF_TimeInterval class to return true if timeinterval1 and timeinterval2 are not equal, and false otherwise.

The arguments are:

timeinterval1
First ESMF_TimeInterval in comparison.
timeinterval2
Second ESMF_TimeInterval in comparison.

36.4.11 ESMF_TimeIntervalOperator(<) - Test if TimeInterval 1 is less than TimeInterval 2


INTERFACE:

       interface operator(<)
       if (timeinterval1 < timeinterval2) then ... endif
                    OR
       result = (timeinterval1 < timeinterval2)
RETURN VALUE:
       logical :: result
ARGUMENTS:
       type(ESMF_TimeInterval), intent(in) :: timeinterval1
       type(ESMF_TimeInterval), intent(in) :: timeinterval2
DESCRIPTION:

Overloads the (<) operator for the ESMF_TimeInterval class to return true if timeinterval1 is less than timeinterval2, and false otherwise.

The arguments are:

timeinterval1
First ESMF_TimeInterval in comparison.
timeinterval2
Second ESMF_TimeInterval in comparison.

36.4.12 ESMF_TimeIntervalOperator(<=) - Test if TimeInterval 1 is less than or equal to TimeInterval 2


INTERFACE:

       interface operator(<=)
       if (timeinterval1 <= timeinterval2) then ... endif
                    OR
       result = (timeinterval1 <= timeinterval2)
RETURN VALUE:
       logical :: result
ARGUMENTS:
       type(ESMF_TimeInterval), intent(in) :: timeinterval1
       type(ESMF_TimeInterval), intent(in) :: timeinterval2
DESCRIPTION:

Overloads the (<=) operator for the ESMF_TimeInterval class to return true if timeinterval1 is less than or equal to timeinterval2, and false otherwise.

The arguments are:

timeinterval1
First ESMF_TimeInterval in comparison.
timeinterval2
Second ESMF_TimeInterval in comparison.

36.4.13 ESMF_TimeIntervalOperator(>) - Test if TimeInterval 1 is greater than TimeInterval 2


INTERFACE:

       interface operator(>)
       if (timeinterval1 > timeinterval2) then ... endif
                    OR
       result = (timeinterval1 > timeinterval2)
RETURN VALUE:
       logical :: result
ARGUMENTS:
       type(ESMF_TimeInterval), intent(in) :: timeinterval1
       type(ESMF_TimeInterval), intent(in) :: timeinterval2
DESCRIPTION:

Overloads the (<) operator for the ESMF_TimeInterval class to return true if timeinterval1 is greater than timeinterval2, and false otherwise.

The arguments are:

timeinterval1
First ESMF_TimeInterval in comparison.
timeinterval2
Second ESMF_TimeInterval in comparison.

36.4.14 ESMF_TimeIntervalOperator(>=) - Test if TimeInterval 1 is greater than or equal to TimeInterval 2


INTERFACE:

       interface operator(>=)
       if (timeinterval1 >= timeinterval2) then ... endif
                    OR
       result = (timeinterval1 >= timeinterval2)
RETURN VALUE:
       logical :: result
ARGUMENTS:
       type(ESMF_TimeInterval), intent(in) :: timeinterval1
       type(ESMF_TimeInterval), intent(in) :: timeinterval2
DESCRIPTION:

Overloads the (<=) operator for the ESMF_TimeInterval class to return true if timeinterval1 is greater than or equal to timeinterval2, and false otherwise.

The arguments are:

timeinterval1
First ESMF_TimeInterval in comparison.
timeinterval2
Second ESMF_TimeInterval in comparison.

36.4.15 ESMF_TimeIntervalAbsValue - Get the absolute value of a TimeInterval


INTERFACE:

       function ESMF_TimeIntervalAbsValue(timeinterval)
RETURN VALUE:
       type(ESMF_TimeInterval) :: ESMF_TimeIntervalAbsValue
ARGUMENTS:
       type(ESMF_TimeInterval), intent(in) :: timeinterval
DESCRIPTION:

Returns the absolute value of timeinterval.

The argument is:

timeinterval
The object instance to take the absolute value of. Absolute value is returned as the value of the function.

36.4.16 ESMF_TimeIntervalGet - Get a TimeInterval value


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, calendarType, &
                                          timeString, timeStringISOFrac, rc)
ARGUMENTS:
       type(ESMF_TimeInterval), intent(inout)         :: timeinterval
       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_CalendarType), intent(out), optional :: calendarType
       character (len=*),       intent(out), optional :: timeString
       character (len=*),       intent(out), optional :: timeStringISOFrac
       integer,                 intent(out), optional :: rc
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.

See ../include/ESMC_BaseTime.h and ../include/ESMC_TimeInterval.h for complete description.

For timeString, converts ESMF_TimeInterval's value into partial ISO 8601 format PyYmMdDThHmMs[:n/d]S. See [19] and  [2]. See also method ESMF_TimeIntervalPrint().

For timeStringISOFrac, converts ESMF_TimeInterval's value into full ISO 8601 format PyYmMdDThHmMs[.f]S. See [19] and  [2]. See also method ESMF_TimeIntervalPrint().

The arguments are:

timeinterval
The object instance to query.
[yy]
Integer years (>= 32-bit).
[yy_i8]
Integer years (large, >= 64-bit).
[mm]
Integer months (>= 32-bit).
[mm_i8]
Integer months (large, >= 64-bit).
[d]
Integer Julian, or Modified Julian, days (>= 32-bit).
[d_i8]
Integer Julian, or Modified Julian, days (large, >= 64-bit).
[h]
Integer hours.
[m]
Integer minutes.
[s]
Integer seconds (>= 32-bit).
[s_i8]
Integer seconds (large, >= 64-bit).
[ms]
Integer milliseconds.
[us]
Integer microseconds.
[ns]
Integer nanoseconds.
[d_r8]
Double precision days.
[h_r8]
Double precision hours.
[m_r8]
Double precision minutes.
[s_r8]
Double precision seconds.
[ms_r8]
Double precision milliseconds.
[us_r8]
Double precision microseconds.
[ns_r8]
Double precision nanoseconds.
[sN]
Integer numerator of fractional seconds (sN/sD).
[sN_i8]
Integer numerator of fractional seconds (sN_i8/sD_i8) (large, >= 64-bit).
[sD]
Integer denominator of fractional seconds (sN/sD).
[sD_i8]
Integer denominator of fractional seconds (sN_i8/sD_i8) (large, >= 64-bit).
[startTime]
Starting time, if set, of an absolute calendar interval (yy, mm, and/or d).
[calendar]
Associated Calendar, if any.
[calendarType]
Associated CalendarType, if any.
[timeString]
Convert time interval value to format string PyYmMdDThHmMs[:n/d]S, where n/d is numerator/denominator of any fractional seconds and all other units are in ISO 8601 format. See [19] and  [2]. See also method ESMF_TimeIntervalPrint().
[timeStringISOFrac]
Convert time interval value to strict ISO 8601 format string PyYmMdDThHmMs[.f], where f is decimal form of any fractional seconds. See [19] and [2]. See also method ESMF_TimeIntervalPrint().
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

36.4.17 ESMF_TimeIntervalGet - Get a TimeInterval value


INTERFACE:

       ! Private name; call using ESMF_TimeIntervalGet()
       subroutine ESMF_TimeIntervalGetDurStart(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, calendarType, &
                                               startTimeIn, &
                                               timeString, timeStringISOFrac, rc)
ARGUMENTS:
       type(ESMF_TimeInterval), intent(inout)         :: timeinterval
       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_CalendarType), intent(out), optional :: calendarType
       type(ESMF_Time),         intent(inout)         :: startTimeIn    ! Input
       character (len=*),       intent(out), optional :: timeString
       character (len=*),       intent(out), optional :: timeStringISOFrac
       integer,                 intent(out), optional :: rc
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.

See ../include/ESMC_BaseTime.h and ../include/ESMC_TimeInterval.h for complete description.

For timeString, converts ESMF_TimeInterval's value into partial ISO 8601 format PyYmMdDThHmMs[:n/d]S. See [19] and  [2]. See also method ESMF_TimeIntervalPrint().

For timeStringISOFrac, converts ESMF_TimeInterval's value into full ISO 8601 format PyYmMdDThHmMs[.f]S. See [19] and  [2]. See also method ESMF_TimeIntervalPrint().

The arguments are:

timeinterval
The object instance to query.
[yy]
Integer years (>= 32-bit).
[yy_i8]
Integer years (large, >= 64-bit).
[mm]
Integer months (>= 32-bit).
[mm_i8]
Integer months (large, >= 64-bit).
[d]
Integer Julian, or Modified Julian, days (>= 32-bit).
[d_i8]
Integer Julian, or Modified Julian, days (large, >= 64-bit).
[h]
Integer hours.
[m]
Integer minutes.
[s]
Integer seconds (>= 32-bit).
[s_i8]
Integer seconds (large, >= 64-bit).
[ms]
Integer milliseconds.
[us]
Integer microseconds.
[ns]
Integer nanoseconds.
[d_r8]
Double precision days.
[h_r8]
Double precision hours.
[m_r8]
Double precision minutes.
[s_r8]
Double precision seconds.
[ms_r8]
Double precision milliseconds.
[us_r8]
Double precision microseconds.
[ns_r8]
Double precision nanoseconds.
[sN]
Integer numerator of fractional seconds (sN/sD).
[sN_i8]
Integer numerator of fractional seconds (sN_i8/sD_i8) (large, >= 64-bit).
[sD]
Integer denominator of fractional seconds (sN/sD).
[sD_i8]
Integer denominator of fractional seconds (sN_i8/sD_i8) (large, >= 64-bit).
[startTime]
Starting time, if set, of an absolute calendar interval (yy, mm, and/or d).
[calendar]
Associated Calendar, if any.
[calendarType]
Associated CalendarType, if any.
startTimeIn
INPUT argument: pins a calendar interval to a specific point in time to allow conversion between relative units (yy, mm, d) and absolute units (d, h, m, s). Overrides any startTime and/or endTime previously set. Mutually exclusive with endTimeIn and calendarIn.
[timeString]
Convert time interval value to format string PyYmMdDThHmMs[:n/d]S, where n/d is numerator/denominator of any fractional seconds and all other units are in ISO 8601 format. See [19] and  [2]. See also method ESMF_TimeIntervalPrint().
[timeStringISOFrac]
Convert time interval value to strict ISO 8601 format string PyYmMdDThHmMs[.f], where f is decimal form of any fractional seconds. See [19] and [2]. See also method ESMF_TimeIntervalPrint().
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

36.4.18 ESMF_TimeIntervalGet - Get a TimeInterval value


INTERFACE:

       ! Private name; call using ESMF_TimeIntervalGet()
       subroutine ESMF_TimeIntervalGetDurCal(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, calendarType, &
                                             calendarIn, &
                                             timeString, timeStringISOFrac, rc)
ARGUMENTS:
       type(ESMF_TimeInterval), intent(inout)         :: timeinterval
       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(inout), optional :: startTime
       type(ESMF_Calendar),     intent(out), optional :: calendar
       type(ESMF_CalendarType), intent(out), optional :: calendarType
       type(ESMF_Calendar),     intent(in)            :: calendarIn     ! Input
       character (len=*),       intent(out), optional :: timeString
       character (len=*),       intent(out), optional :: timeStringISOFrac
       integer,                 intent(out), optional :: rc
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.

See ../include/ESMC_BaseTime.h and ../include/ESMC_TimeInterval.h for complete description.

For timeString, converts ESMF_TimeInterval's value into partial ISO 8601 format PyYmMdDThHmMs[:n/d]S. See [19] and  [2]. See also method ESMF_TimeIntervalPrint().

For timeStringISOFrac, converts ESMF_TimeInterval's value into full ISO 8601 format PyYmMdDThHmMs[.f]S. See [19] and  [2]. See also method ESMF_TimeIntervalPrint().

The arguments are:

timeinterval
The object instance to query.
[yy]
Integer years (>= 32-bit).
[yy_i8]
Integer years (large, >= 64-bit).
[mm]
Integer months (>= 32-bit).
[mm_i8]
Integer months (large, >= 64-bit).
[d]
Integer Julian, or Modified Julian, days (>= 32-bit).
[d_i8]
Integer Julian, or Modified Julian, days (large, >= 64-bit).
[h]
Integer hours.
[m]
Integer minutes.
[s]
Integer seconds (>= 32-bit).
[s_i8]
Integer seconds (large, >= 64-bit).
[ms]
Integer milliseconds.
[us]
Integer microseconds.
[ns]
Integer nanoseconds.
[d_r8]
Double precision days.
[h_r8]
Double precision hours.
[m_r8]
Double precision minutes.
[s_r8]
Double precision seconds.
[ms_r8]
Double precision milliseconds.
[us_r8]
Double precision microseconds.
[ns_r8]
Double precision nanoseconds.
[sN]
Integer numerator of fractional seconds (sN/sD).
[sN_i8]
Integer numerator of fractional seconds (sN_i8/sD_i8) (large, >= 64-bit).
[sD]
Integer denominator of fractional seconds (sN/sD).
[sD_i8]
Integer denominator of fractional seconds (sN_i8/sD_i8) (large, >= 64-bit).
[startTime]
Starting time, if set, of an absolute calendar interval (yy, mm, and/or d).
[calendar]
Associated Calendar, if any.
[calendarType]
Associated CalendarType, if any.
[calendarIn]
INPUT argument: pins a calendar interval to a specific calendar to allow conversion between relative units (yy, mm, d) and absolute units (d, h, m, s). Mutually exclusive with startTimeIn and endTimeIn since they contain a calendar. Alternate to, and mutually exclusive with, calendarTypeIn below. Primarily for specifying a custom calendar type.
[timeString]
Convert time interval value to format string PyYmMdDThHmMs[:n/d]S, where n/d is numerator/denominator of any fractional seconds and all other units are in ISO 8601 format. See [19] and  [2]. See also method ESMF_TimeIntervalPrint().
[timeStringISOFrac]
Convert time interval value to strict ISO 8601 format string PyYmMdDThHmMs[.f], where f is decimal form of any fractional seconds. See [19] and [2]. See also method ESMF_TimeIntervalPrint().
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

36.4.19 ESMF_TimeIntervalGet - Get a TimeInterval value


INTERFACE:

       ! Private name; call using ESMF_TimeIntervalGet()
       subroutine ESMF_TimeIntervalGetDurCalTyp(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, calendarType, &
                                                calendarTypeIn, &
                                                timeString, &
                                                timeStringISOFrac, rc)
ARGUMENTS:
       type(ESMF_TimeInterval), intent(inout)         :: timeinterval
       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_CalendarType), intent(out), optional :: calendarType
       type(ESMF_CalendarType), intent(in)            :: calendarTypeIn ! Input
       character (len=*),       intent(out), optional :: timeString
       character (len=*),       intent(out), optional :: timeStringISOFrac
       integer,                 intent(out), optional :: rc
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.

See ../include/ESMC_BaseTime.h and ../include/ESMC_TimeInterval.h for complete description.

For timeString, converts ESMF_TimeInterval's value into partial ISO 8601 format PyYmMdDThHmMs[:n/d]S. See [19] and  [2]. See also method ESMF_TimeIntervalPrint().

For timeStringISOFrac, converts ESMF_TimeInterval's value into full ISO 8601 format PyYmMdDThHmMs[.f]S. See [19] and  [2]. See also method ESMF_TimeIntervalPrint().

The arguments are:

timeinterval
The object instance to query.
[yy]
Integer years (>= 32-bit).
[yy_i8]
Integer years (large, >= 64-bit).
[mm]
Integer months (>= 32-bit).
[mm_i8]
Integer months (large, >= 64-bit).
[d]
Integer Julian, or Modified Julian, days (>= 32-bit).
[d_i8]
Integer Julian, or Modified Julian, days (large, >= 64-bit).
[h]
Integer hours.
[m]
Integer minutes.
[s]
Integer seconds (>= 32-bit).
[s_i8]
Integer seconds (large, >= 64-bit).
[ms]
Integer milliseconds.
[us]
Integer microseconds.
[ns]
Integer nanoseconds.
[d_r8]
Double precision days.
[h_r8]
Double precision hours.
[m_r8]
Double precision minutes.
[s_r8]
Double precision seconds.
[ms_r8]
Double precision milliseconds.
[us_r8]
Double precision microseconds.
[ns_r8]
Double precision nanoseconds.
[sN]
Integer numerator of fractional seconds (sN/sD).
[sN_i8]
Integer numerator of fractional seconds (sN_i8/sD_i8) (large, >= 64-bit).
[sD]
Integer denominator of fractional seconds (sN/sD).
[sD_i8]
Integer denominator of fractional seconds (sN_i8/sD_i8) (large, >= 64-bit).
[startTime]
Starting time, if set, of an absolute calendar interval (yy, mm, and/or d).
[calendar]
Associated Calendar, if any.
[calendarType]
Associated CalendarType, if any.
[calendarTypeIn]
INPUT argument: Alternate to, and mutually exclusive with, calendarIn above. More convenient way of specifying a built-in calendar type.
[timeString]
Convert time interval value to format string PyYmMdDThHmMs[:n/d]S, where n/d is numerator/denominator of any fractional seconds and all other units are in ISO 8601 format. See [19] and  [2]. See also method ESMF_TimeIntervalPrint().
[timeStringISOFrac]
Convert time interval value to strict ISO 8601 format string PyYmMdDThHmMs[.f], where f is decimal form of any fractional seconds. See [19] and [2]. See also method ESMF_TimeIntervalPrint().
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

36.4.20 ESMF_TimeIntervalNegAbsValue - Get the negative absolute value of a TimeInterval


INTERFACE:

       function ESMF_TimeIntervalNegAbsValue(timeinterval)
RETURN VALUE:
       type(ESMF_TimeInterval) :: ESMF_TimeIntervalNegAbsValue
ARGUMENTS:
       type(ESMF_TimeInterval), intent(inout) :: timeinterval
DESCRIPTION:

Returns the negative absolute value of timeinterval.

The argument is:

timeinterval
The object instance to take the negative absolute value of. Negative absolute value is returned as the value of the function.

36.4.21 ESMF_TimeIntervalPrint - Print the contents of a TimeInterval


INTERFACE:

       subroutine ESMF_TimeIntervalPrint(timeinterval, options, rc)
ARGUMENTS:
       type(ESMF_TimeInterval), intent(inout)         :: timeinterval
       character (len=*),       intent(in),  optional :: options
       integer,                 intent(out), optional :: rc
DESCRIPTION:

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.

Note: Many ESMF_<class>Print methods are implemented in C++. On some platforms/compilers there is a potential issue with interleaving Fortran and C++ output to stdout such that it doesn't appear in the expected order. If this occurs, the ESMF_IOUnitFlush() method may be used on unit 6 to get coherent output.

The arguments are:

timeinterval
Time interval to be printed out.
[options]
Print options. If none specified, prints all timeinterval property values.
"string" - prints timeinterval's value in ISO 8601 format for all units through seconds. For any non-zero fractional seconds, prints in integer rational fraction form n/d. Format is PyYmMdDThHmMs[:n/d]S, where [:n/d] is the integer numerator and denominator of the fractional seconds value, if present. See [19] and [2]. See also method ESMF_TimeIntervalGet(..., timeString= , ...)
"string isofrac" - prints timeinterval's value in strict ISO 8601 format for all units, including any fractional seconds part. Format is PyYmMdDThHmMs[.f]S, where [.f] represents fractional seconds in decimal form, if present. See [19] and [2]. See also method ESMF_TimeIntervalGet(..., timeStringISOFrac= , ...)
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

36.4.22 ESMF_TimeIntervalSet - Initialize or set a TimeInterval


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
       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 :: rc
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:

timeinterval
The object instance to initialize.
[yy]
Integer years (>= 32-bit). Default = 0
[yy_i8]
Integer years (large, >= 64-bit). Default = 0
[mm]
Integer months (>= 32-bit). Default = 0
[mm_i8]
Integer months (large, >= 64-bit). Default = 0
[d]
Integer Julian, or Modified Julian, days (>= 32-bit). Default = 0
[d_i8]
Integer Julian, or Modified Julian, days (large, >= 64-bit). Default = 0
[h]
Integer hours. Default = 0
[m]
Integer minutes. Default = 0
[s]
Integer seconds (>= 32-bit). Default = 0
[s_i8]
Integer seconds (large, >= 64-bit). Default = 0
[ms]
Integer milliseconds. Default = 0
[us]
Integer microseconds. Default = 0
[ns]
Integer nanoseconds. Default = 0
[d_r8]
Double precision days. Default = 0.0.
[h_r8]
Double precision hours. Default = 0.0.
[m_r8]
Double precision minutes. Default = 0.0.
[s_r8]
Double precision seconds. Default = 0.0.
[ms_r8]
Double precision milliseconds. Default = 0.0.
[us_r8]
Double precision microseconds. Default = 0.0.
[ns_r8]
Double precision nanoseconds. Default = 0.0.
[sN]
Integer numerator of fractional seconds (sN/sD). Default = 0
[sN_i8]
Integer numerator of fractional seconds (sN_i8/sD_i8) (large, >= 64-bit). Default = 0
[sD]
Integer denominator of fractional seconds (sN/sD). Default = 1
[sD_i8]
Integer denominator of fractional seconds (sN_i8/sD_i8) (large, >= 64-bit). Default = 1
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

36.4.23 ESMF_TimeIntervalSet - Initialize or set a TimeInterval


INTERFACE:

       ! Private name; call using ESMF_TimeIntervalSet()
       subroutine ESMF_TimeIntervalSetDurStart(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, rc)
ARGUMENTS:
       type(ESMF_TimeInterval), intent(inout)         :: timeinterval
       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
       type(ESMF_Time),         intent(in)            :: startTime
       integer,                 intent(out), optional :: rc
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:

timeinterval
The object instance to initialize.
[yy]
Integer years (>= 32-bit). Default = 0
[yy_i8]
Integer years (large, >= 64-bit). Default = 0
[mm]
Integer months (>= 32-bit). Default = 0
[mm_i8]
Integer months (large, >= 64-bit). Default = 0
[d]
Integer Julian, or Modified Julian, days (>= 32-bit). Default = 0
[d_i8]
Integer Julian, or Modified Julian, days (large, >= 64-bit). Default = 0
[h]
Integer hours. Default = 0
[m]
Integer minutes. Default = 0
[s]
Integer seconds (>= 32-bit). Default = 0
[s_i8]
Integer seconds (large, >= 64-bit). Default = 0
[ms]
Integer milliseconds. Default = 0
[us]
Integer microseconds. Default = 0
[ns]
Integer nanoseconds. Default = 0
[d_r8]
Double precision days. Default = 0.0.
[h_r8]
Double precision hours. Default = 0.0.
[m_r8]
Double precision minutes. Default = 0.0.
[s_r8]
Double precision seconds. Default = 0.0.
[ms_r8]
Double precision milliseconds. Default = 0.0.
[us_r8]
Double precision microseconds. Default = 0.0.
[ns_r8]
Double precision nanoseconds. Default = 0.0.
[sN]
Integer numerator of fractional seconds (sN/sD). Default = 0
[sN_i8]
Integer numerator of fractional seconds (sN_i8/sD_i8) (large, >= 64-bit). Default = 0
[sD]
Integer denominator of fractional seconds (sN/sD). Default = 1
[sD_i8]
Integer denominator of fractional seconds (sN_i8/sD_i8). (large, >= 64-bit). Default = 1
startTime
Starting time of an absolute calendar interval (yy, mm, and/or d); pins a calendar interval to a specific point in time. If not set, and calendar also not set, calendar interval "floats" across all calendars and times.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

36.4.24 ESMF_TimeIntervalSet - Initialize or set a TimeInterval


INTERFACE:

       ! Private name; call using ESMF_TimeIntervalSet()
       subroutine ESMF_TimeIntervalSetDurCal(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, calendar, rc)
ARGUMENTS:
       type(ESMF_TimeInterval), intent(inout)         :: timeinterval
       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
       type(ESMF_Calendar),     intent(in)            :: calendar
       integer,                 intent(out), optional :: rc
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:

timeinterval
The object instance to initialize.
[yy]
Integer years (>= 32-bit). Default = 0
[yy_i8]
Integer years (large, >= 64-bit). Default = 0
[mm]
Integer months (>= 32-bit). Default = 0
[mm_i8]
Integer months (large, >= 64-bit). Default = 0
[d]
Integer Julian, or Modified Julian, days (>= 32-bit). Default = 0
[d_i8]
Integer Julian, or Modified Julian, days (large, >= 64-bit). Default = 0
[h]
Integer hours. Default = 0
[m]
Integer minutes. Default = 0
[s]
Integer seconds (>= 32-bit). Default = 0
[s_i8]
Integer seconds (large, >= 64-bit). Default = 0
[ms]
Integer milliseconds. Default = 0
[us]
Integer microseconds. Default = 0
[ns]
Integer nanoseconds. Default = 0
[d_r8]
Double precision days. Default = 0.0.
[h_r8]
Double precision hours. Default = 0.0.
[m_r8]
Double precision minutes. Default = 0.0.
[s_r8]
Double precision seconds. Default = 0.0.
[ms_r8]
Double precision milliseconds. Default = 0.0.
[us_r8]
Double precision microseconds. Default = 0.0.
[ns_r8]
Double precision nanoseconds. Default = 0.0.
[sN]
Integer numerator of fractional seconds (sN/sD). Default = 0
[sN_i8]
Integer numerator of fractional seconds (sN_i8/sD_i8). (large, >= 64-bit). Default = 0
[sD]
Integer denominator of fractional seconds (sN/sD). Default = 1
[sD_i8]
Integer denominator of fractional seconds (sN_i8/sD_i8). (large, >= 64-bit). Default = 1
[calendar]
Calendar used to give better definition to calendar interval (yy, mm, and/or d) for arithmetic, comparison, and conversion operations. Allows calendar interval to "float" across all times on a specific calendar. Default = NULL; if startTime also not specified, calendar interval "floats" across all calendars and times. Mutually exclusive with startTime since it contains a calendar. Alternate to, and mutually exclusive with, calendarType below. Primarily for specifying a custom calendar type.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

36.4.25 ESMF_TimeIntervalSet - Initialize or set a TimeInterval


INTERFACE:

       ! Private name; call using ESMF_TimeIntervalSet()
       subroutine ESMF_TimeIntervalSetDurCalTyp(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, &
                                                calendarType, rc)
ARGUMENTS:
       type(ESMF_TimeInterval), intent(inout)         :: timeinterval
       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
       type(ESMF_CalendarType), intent(in)            :: calendarType
       integer,                 intent(out), optional :: rc
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:

timeinterval
The object instance to initialize.
[yy]
Integer years (>= 32-bit). Default = 0
[yy_i8]
Integer years (large, >= 64-bit). Default = 0
[mm]
Integer months (>= 32-bit). Default = 0
[mm_i8]
Integer months (large, >= 64-bit). Default = 0
[d]
Integer Julian, or Modified Julian, days (>= 32-bit). Default = 0
[d_i8]
Integer Julian, or Modified Julian, days (large, >= 64-bit). Default = 0
[h]
Integer hours. Default = 0
[m]
Integer minutes. Default = 0
[s]
Integer seconds (>= 32-bit). Default = 0
[s_i8]
Integer seconds (large, >= 64-bit). Default = 0
[ms]
Integer milliseconds. Default = 0
[us]
Integer microseconds. Default = 0
[ns]
Integer nanoseconds. Default = 0
[d_r8]
Double precision days. Default = 0.0.
[h_r8]
Double precision hours. Default = 0.0.
[m_r8]
Double precision minutes. Default = 0.0.
[s_r8]
Double precision seconds. Default = 0.0.
[ms_r8]
Double precision milliseconds. Default = 0.0.
[us_r8]
Double precision microseconds. Default = 0.0.
[ns_r8]
Double precision nanoseconds. Default = 0.0.
[sN]
Integer numerator of fractional seconds (sN/sD). Default = 0
[sN_i8]
Integer numerator of fractional seconds (sN_i8/sD_i8) (large, >= 64-bit). Default = 0
[sD]
Integer denominator of fractional seconds (sN/sD). Default = 1
[sD_i8]
Integer denominator of fractional seconds (sN_i8/sD_i8) (large, >= 64-bit). Default = 1
[calendarType]
Alternate to, and mutually exclusive with, calendar above. More convenient way of specifying a built-in calendar type.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

36.4.26 ESMF_TimeIntervalValidate - Validate a TimeInterval


INTERFACE:

       subroutine ESMF_TimeIntervalValidate(timeinterval, options, rc)
ARGUMENTS:
       type(ESMF_TimeInterval), intent(inout)         :: timeinterval
       character (len=*),       intent(in),  optional :: options
       integer,                 intent(out), optional :: rc
DESCRIPTION:

Checks whether a timeinterval is valid. If fractional value, denominator must be non-zero. The options control the type of validation.

The arguments are:

timeinterval
ESMF_TimeInterval to be validated.
[options]
Validation options are not yet supported.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

37 Clock Class

37.1 Description

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 38.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.

37.2 Clock Options

37.2.1 ESMF_Direction

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_MODE_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.

Valid values are:

ESMF_MODE_FORWARD
Upon calling ESMF_ClockAdvance(), the clock will timestep from its startTime toward its stopTime. This is the default direction. A user can use either ESMF_ClockIsStopTime() or ESMF_ClockIsDone() methods to determine when stopTime is reached. This forward behavior also holds for negative timestep clocks which are initialized (created) with stopTime < startTime.

ESMF_MODE_REVERSE
Upon calling ESMF_ClockAdvance(), the clock will timestep backwards toward its startTime. Use method ESMF_ClockIsDone() to determine when startTime is reached. This reverse behavior also holds for negative timestep clocks which are initialized (created) with stopTime < startTime.

37.3 Use and Examples

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
!-----------------------------------------------------------------------------

      ! ESMF Framework module
      use ESMF_Mod
      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(defaultCalendar=ESMF_CAL_GREGORIAN, rc=rc)

37.3.1 Clock Creation

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("Clock 1", timeStep, startTime, stopTime, rc=rc)

37.3.2 Clock Advance

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))

        call ESMF_ClockPrint(clock, "currTime string", rc)

        call ESMF_ClockAdvance(clock, rc=rc)

      end do

37.3.3 Clock Examination

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."

37.3.4 Clock Reversal

This example shows how to time-step an ESMF_Clock in reverse mode.

      call ESMF_ClockSet(clock, direction=ESMF_MODE_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))

        call ESMF_ClockPrint(clock, "currTime string", rc)

        call ESMF_ClockAdvance(clock, rc=rc)

      end do

37.3.5 Clock Destruction

This example shows how to destroy an ESMF_Clock.

      ! destroy clock
      call ESMF_ClockDestroy(clock, rc)

      ! finalize ESMF framework
      call ESMF_Finalize(rc=rc)

      end program ESMF_ClockEx

37.4 Restrictions and Future Work

  1. Alarm list allocation factor The alarm list within a clock is dynamically allocated automatically, 200 alarm references at a time. This constant is defined in both Fortran and C++ with a #define for ease of modification.

  2. Clock variable timesteps in reverse In order for a clock with variable timesteps to be run in ESMF_MODE_REVERSE, the user must supply those timesteps to ESMF_ClockAdvance(). Essentially, the user must save the timesteps while in forward mode. In a future release, the Time Manager will assume this responsibility by saving the clock state (including the timeStep) at every timestep while in forward mode.

37.5 Class API

37.5.1 ESMF_ClockOperator(==) - Test if Clock 1 is equal to Clock 2


INTERFACE:

       interface operator(==)
       if (clock1 == clock2) then ... endif
                    OR
       result = (clock1 == clock2)
RETURN VALUE:
       logical :: result
ARGUMENTS:
       type(ESMF_Clock), intent(in) :: clock1
       type(ESMF_Clock), intent(in) :: clock2
DESCRIPTION:

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.

The arguments are:

clock1
The first ESMF_Clock in comparison.
clock2
The second ESMF_Clock in comparison.

37.5.2 ESMF_ClockOperator(/=) - Test if Clock 1 is not equal to Clock 2


INTERFACE:

       interface operator(/=)
       if (clock1 /= clock2) then ... endif
                    OR
       result = (clock1 /= clock2)
RETURN VALUE:
       logical :: result
ARGUMENTS:
       type(ESMF_Clock), intent(in) :: clock1
       type(ESMF_Clock), intent(in) :: clock2
DESCRIPTION:

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.

The arguments are:

clock1
The first ESMF_Clock in comparison.
clock2
The second ESMF_Clock in comparison.

37.5.3 ESMF_ClockAdvance - Advance a Clock's current time by one time step


INTERFACE:

       subroutine ESMF_ClockAdvance(clock, timeStep, ringingAlarmList, &
                                    ringingAlarmCount, rc)
ARGUMENTS:
       type(ESMF_Clock),               intent(inout)         :: clock
       type(ESMF_TimeInterval),        intent(inout), optional :: timeStep
       type(ESMF_Alarm), dimension(:), intent(out), optional :: ringingAlarmList
       integer,                        intent(out), optional :: ringingAlarmCount
       integer,                        intent(out), optional :: rc
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_MODE_FORWARD (default), this method adds the timeStep to the clock's current time. In ESMF_MODE_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:

clock
The object instance to advance.
[timeStep]
Time step is performed with given timeStep, instead of the ESMF_Clock's. Does not replace the ESMF_Clock's timeStep; use ESMF_ClockSet(clock, timeStep, ...) for this purpose. Supports applications with variable time steps. timeStep can be positive or negative.
[ringingAlarmList]
Returns the array of alarms that are ringing after the time step.
[ringingAlarmCount]
The number of alarms ringing after the time step.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

37.5.4 ESMF_ClockCreate - Create a new ESMF Clock


INTERFACE:

       ! Private name; call using ESMF_ClockCreate()
       function ESMF_ClockCreateNew(name, timeStep, startTime, stopTime, &
                                    runDuration, runTimeStepCount, refTime, rc)
RETURN VALUE:
       type(ESMF_Clock) :: ESMF_ClockCreateNew
ARGUMENTS:
       character (len=*),       intent(in),  optional :: name
       type(ESMF_TimeInterval), intent(in)            :: timeStep
       type(ESMF_Time),         intent(in)            :: 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
       integer,                 intent(out), optional :: rc
DESCRIPTION:

Creates and sets the initial values in a new ESMF_Clock.

This is a private method; invoke via the public overloaded entry point ESMF_ClockCreate().

The arguments are:

[name]
The name for the newly created clock. If not specified, a default unique name will be generated: "ClockNNN" where NNN is a unique sequence number from 001 to 999.
timeStep
The ESMF_Clock's time step interval, which can be positive or negative.
startTime
The ESMF_Clock's starting time. Can be less than or or greater than stopTime, depending on a positive or negative timeStep, respectively, and whether a stopTime is specified; see below.
[stopTime]
The ESMF_Clock's stopping time. Can be greater than or less than the startTime, depending on a positive or negative timeStep, respectively. If neither stopTime, runDuration, nor runTimeStepCount is specified, clock runs "forever"; user must use other means to know when to stop (e.g. ESMF_Alarm or ESMF_ClockGet(clock, currTime)). Mutually exclusive with runDuration and runTimeStepCount.
[runDuration]
Alternative way to specify ESMF_Clock's stopping time; stopTime = startTime + runDuration. Can be positive or negative, consistent with the timeStep's sign. Mutually exclusive with stopTime and runTimeStepCount.
[runTimeStepCount]
Alternative way to specify ESMF_Clock's stopping time; stopTime = startTime + (runTimeStepCount * timeStep). stopTime can be before startTime if timeStep is negative. Mutually exclusive with stopTime and runDuration.
[refTime]
The ESMF_Clock's reference time. Provides reference point for simulation time (see currSimTime in ESMF_ClockGet() below).
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

37.5.5 ESMF_ClockCreate - Create a copy of an existing ESMF Clock


INTERFACE:

       ! Private name; call using ESMF_ClockCreate()
       function ESMF_ClockCreateCopy(clock, rc)
RETURN VALUE:
       type(ESMF_Clock) :: ESMF_ClockCreateCopy
ARGUMENTS:
       type(ESMF_Clock), intent(in)            :: clock
       integer,          intent(out), optional :: rc
DESCRIPTION:

Creates a copy of a given ESMF_Clock.

This is a private method; invoke via the public overloaded entry point ESMF_ClockCreate().

The arguments are:

clock
The ESMF_Clock to copy.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

37.5.6 ESMF_ClockDestroy - Free all resources associated with a Clock


INTERFACE:

       subroutine ESMF_ClockDestroy(clock, rc)
ARGUMENTS:
       type(ESMF_Clock)               :: clock
       integer, intent(out), optional :: rc
DESCRIPTION:

Releases all resources associated with this ESMF_Clock.

The arguments are:

clock
Destroy contents of this ESMF_Clock.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

37.5.7 ESMF_ClockGet - Get a Clock's properties


INTERFACE:

       subroutine ESMF_ClockGet(clock, name, timeStep, startTime, stopTime, &
                                runDuration, runTimeStepCount, refTime, &
                                currTime, prevTime, currSimTime, prevSimTime, &
                                calendar, calendarType, timeZone, advanceCount, &
                                alarmCount, direction, rc)
ARGUMENTS:
       type(ESMF_Clock),        intent(in)            :: clock
       character (len=*),       intent(out), optional :: name
       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_CalendarType), intent(out), optional :: calendarType
       integer,                 intent(out), optional :: timeZone
       integer(ESMF_KIND_I8),   intent(out), optional :: advanceCount
       integer,                 intent(out), optional :: alarmCount
       type(ESMF_Direction),    intent(out), optional :: direction
       integer,                 intent(out), optional :: rc
DESCRIPTION:

Gets one or more of the properties of an ESMF_Clock.

The arguments are:

clock
The object instance to query.
[name]
The name of this clock.
[timeStep]
The ESMF_Clock's time step interval.
[startTime]
The ESMF_Clock's starting time.
[stopTime]
The ESMF_Clock's stopping time.
[runDuration]
Alternative way to get ESMF_Clock's stopping time; runDuration = stopTime - startTime.
[runTimeStepCount]
Alternative way to get ESMF_Clock's stopping time; runTimeStepCount = (stopTime - startTime) / timeStep.
[refTime]
The ESMF_Clock's reference time.
[currTime]
The ESMF_Clock's current time.
[prevTime]
The ESMF_Clock's previous time. Equals currTime at the previous time step.
[currSimTime]
The current simulation time (currTime - refTime).
[prevSimTime]
The previous simulation time. Equals currSimTime at the previous time step.
[calendar]
The Calendar on which all the Clock's times are defined.
[calendarType]
The CalendarType on which all the Clock's times are defined.
[timeZone]
The timezone within which all the Clock's times are defined.
[advanceCount]
The number of times the ESMF_Clock has been advanced. Increments in ESMF_MODE_FORWARD and decrements in ESMF_MODE_REVERSE; see "direction" argument below and in ESMF_ClockSet().
[alarmCount]
The number of ESMF_Alarms in the ESMF_Clock's ESMF_Alarm list.
[direction]
The ESMF_Clock's time stepping direction. See also ESMF_ClockIsReverse(), an alternative for convenient use in "if" and "do while" constructs.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

37.5.8 ESMF_ClockGetAlarm - Get an Alarm in a Clock's Alarm list


INTERFACE:

       subroutine ESMF_ClockGetAlarm(clock, name, alarm, rc)
ARGUMENTS:
       type(ESMF_Clock),  intent(inout)         :: clock
       character (len=*), intent(in)            :: name
       type(ESMF_Alarm),  intent(out)           :: alarm
       integer,           intent(out), optional :: rc
DESCRIPTION:

Gets the alarm whose name is the value of name in the clock's ESMF_Alarm list.

The arguments are:

clock
The object instance to get the ESMF_Alarm from.
name
The name of the desired ESMF_Alarm.
alarm
The desired alarm.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

37.5.9 ESMF_ClockGetAlarmList - Get a list of Alarms from a Clock


INTERFACE:

       subroutine ESMF_ClockGetAlarmList(clock, alarmListType, &
                                         alarmList, alarmCount, timeStep, rc)
ARGUMENTS:
       type(ESMF_Clock),               intent(in)            :: clock
       type(ESMF_AlarmListType),       intent(in)            :: alarmListType
       type(ESMF_Alarm), dimension(:), intent(out)           :: alarmList
       integer,                        intent(out)           :: alarmCount
       type(ESMF_TimeInterval),        intent(in),  optional :: timeStep
       integer,                        intent(out), optional :: rc
DESCRIPTION:

Gets the clock's list of alarms.

The arguments are:

clock
The object instance from which to get an ESMF_Alarm list.
alarmListType
The type of list to get: 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.

alarmList
The array of returned alarms.
alarmCount
The number of ESMF_Alarms in the returned list.
[timeStep]
Optional time step to be used instead of the clock's. Only used with ESMF_ALARMLIST_NEXTRINGING alarmListType (see above); ignored if specified with other alarmListTypes.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

37.5.10 ESMF_ClockGetNextTime - Calculate a Clock's next time


INTERFACE:

       subroutine ESMF_ClockGetNextTime(clock, nextTime, timeStep, rc)
ARGUMENTS:
       type(ESMF_Clock),        intent(in)              :: clock
       type(ESMF_Time),         intent(out)             :: nextTime
       type(ESMF_TimeInterval), intent(inout), optional :: timeStep
       integer,                 intent(out), optional   :: rc
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:

clock
The object instance for which to get the next time.
nextTime
The resulting ESMF_Clock's next time.
[timeStep]
The time step interval to use instead of the clock's.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

37.5.11 ESMF_ClockIsDone - Based on its direction, test if the Clock has reached or exceeded its stop time or start time


INTERFACE:

       function ESMF_ClockIsDone(clock, rc)
RETURN VALUE:
       logical :: ESMF_ClockIsDone
ARGUMENTS:
       type(ESMF_Clock), intent(in)            :: clock
       integer,          intent(out), optional :: rc
DESCRIPTION:

Returns true if currentTime is greater than or equal to stopTime in ESMF_MODE_FORWARD, or if currentTime is less than or equal to startTime in ESMF_MODE_REVERSE. It returns false otherwise.

The arguments are:

clock
The object instance to check.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

37.5.12 ESMF_ClockIsReverse - Test if the Clock is in reverse mode


INTERFACE:

       function ESMF_ClockIsReverse(clock, rc)
RETURN VALUE:
       logical :: ESMF_ClockIsReverse
ARGUMENTS:
       type(ESMF_Clock), intent(in)            :: clock
       integer,          intent(out), optional :: rc
DESCRIPTION:

Returns true if clock is in ESMF_MODE_REVERSE, and false if in ESMF_MODE_FORWARD. Allows convenient use in "if" and "do while" constructs. Alternative to ESMF_ClockGet(...direction=...).

The arguments are:

clock
The object instance to check.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

37.5.13 ESMF_ClockIsStopTime - Test if the Clock has reached or exceeded its stop time


INTERFACE:

       function ESMF_ClockIsStopTime(clock, rc)
RETURN VALUE:
       logical :: ESMF_ClockIsStopTime
ARGUMENTS:
       type(ESMF_Clock), intent(in)            :: clock
       integer,          intent(out), optional :: rc
DESCRIPTION:

Returns true if the clock has reached or exceeded its stop time, and false otherwise.

The arguments are:

clock
The object instance to check.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

37.5.14 ESMF_ClockIsStopTimeEnabled - Test if the Clock's stop time is enabled


INTERFACE:

       function ESMF_ClockIsStopTimeEnabled(clock, rc)
RETURN VALUE:
       logical :: ESMF_ClockIsStopTimeEnabled
ARGUMENTS:
       type(ESMF_Clock), intent(in)            :: clock
       integer,          intent(out), optional :: rc
DESCRIPTION:

Returns true if the clock's stop time is set and enabled, and false otherwise.

The arguments are:

clock
The object instance to check.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

37.5.15 ESMF_ClockPrint - Print the contents of a Clock


INTERFACE:

       subroutine ESMF_ClockPrint(clock, options, rc)
ARGUMENTS:
       type(ESMF_Clock),  intent(in)            :: clock
       character (len=*), intent(in),  optional :: options
       integer,           intent(out), optional :: rc
DESCRIPTION:

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.

Note: Many ESMF_<class>Print methods are implemented in C++. On some platforms/compilers there is a potential issue with interleaving Fortran and C++ output to stdout such that it doesn't appear in the expected order. If this occurs, the ESMF_IOUnitFlush() method may be used on unit 6 to get coherent output.

The arguments are:

clock
ESMF_Clock to be printed out.
[options]
Print options. If none specified, prints all clock property values.
"advanceCount" - print the number of times the clock has been advanced.
"alarmCount" - print the number of alarms in the clock's list.
"alarmList" - print the clock's alarm list.
"currTime" - print the current clock time.
"direction" - print the clock's timestep direction.
"name" - print the clock's name.
"prevTime" - print the previous clock time.
"refTime" - print the clock's reference time.
"startTime" - print the clock's start time.
"stopTime" - print the clock's stop time.
"timeStep" - print the clock's time step.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

37.5.16 ESMF_ClockSet - Set one or more properties of a Clock


INTERFACE:

       subroutine ESMF_ClockSet(clock, name, timeStep, startTime, stopTime, &
                                runDuration, runTimeStepCount, refTime, &
                                currTime, advanceCount, direction, rc)
ARGUMENTS:
       type(ESMF_Clock),        intent(inout)           :: clock
       character (len=*),       intent(in),    optional :: name
       type(ESMF_TimeInterval), intent(inout), optional :: timeStep
       type(ESMF_Time),         intent(inout), optional :: startTime
       type(ESMF_Time),         intent(inout), optional :: stopTime
       type(ESMF_TimeInterval), intent(inout), optional :: runDuration
       integer,                 intent(in),    optional :: runTimeStepCount
       type(ESMF_Time),         intent(inout), optional :: refTime
       type(ESMF_Time),         intent(inout), optional :: currTime
       integer(ESMF_KIND_I8),   intent(in),    optional :: advanceCount
       type(ESMF_Direction),    intent(in),    optional :: direction
       integer,                 intent(out),   optional :: rc
DESCRIPTION:

Sets/resets one or more of the properties of an ESMF_Clock that was previously initialized via ESMF_ClockCreate().

The arguments are:

clock
The object instance to set.
[name]
The new name for this clock.
[timeStep]
The ESMF_Clock's time step interval, which can be positive or negative. This is used to change a clock's timestep property for those applications that need variable timesteps. See ESMF_ClockAdvance() below for specifying variable timesteps that are NOT saved as the clock's internal time step property. See "direction" argument below for behavior with
t ESMF_MODE_REVERSE direction.
[startTime]
The ESMF_Clock's starting time. Can be less than or or greater than stopTime, depending on a positive or negative timeStep, respectively, and whether a stopTime is specified; see below.
[stopTime]
The ESMF_Clock's stopping time. Can be greater than or less than the startTime, depending on a positive or negative timeStep, respectively. If neither stopTime, runDuration, nor runTimeStepCount is specified, clock runs "forever"; user must use other means to know when to stop (e.g. ESMF_Alarm or ESMF_ClockGet(clock, currTime)). Mutually exclusive with runDuration and runTimeStepCount.
[runDuration]
Alternative way to specify ESMF_Clock's stopping time; stopTime = startTime + runDuration. Can be positive or negative, consistent with the timeStep's sign. Mutually exclusive with stopTime and runTimeStepCount.
[runTimeStepCount]
Alternative way to specify ESMF_Clock's stopping time; stopTime = startTime + (runTimeStepCount * timeStep). stopTime can be before startTime if timeStep is negative. Mutually exclusive with stopTime and runDuration.
[refTime]
The ESMF_Clock's reference time. See description in ESMF_ClockCreate() above.
[currTime]
The current time.
[advanceCount]
The number of times the clock has been timestepped.
[direction]
Sets the clock's time-stepping direction. If called with ESMF_MODE_REVERSE, sets the clock in "reverse" mode, causing it to timestep back towards its startTime. If called with ESMF_MODE_FORWARD, sets the clock in normal, "forward" mode, causing it to timestep in the direction of its startTime to stopTime. This holds true for negative timestep clocks as well, which are initialized (created) with stopTime < startTime. The default mode is ESMF_MODE_FORWARD, established at ESMF_ClockCreate(). timeStep can also be specified as an argument at the same time, which allows for a change in magnitude and/or sign of the clock's timeStep. If not specified with ESMF_MODE_REVERSE, the clock's current timeStep is effectively negated. If timeStep is specified, its sign is used as specified; it is not negated internally. E.g., if the specified timeStep is negative and the clock is placed in ESMF_MODE_REVERSE, subsequent calls to ESMF_ClockAdvance() will cause the clock's current time to be decremented by the new timeStep's magnitude.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

37.5.17 ESMF_ClockStopTimeDisable - Disable a Clock's stop time


INTERFACE:

       subroutine ESMF_ClockStopTimeDisable(clock, rc)
ARGUMENTS:
       type(ESMF_Clock), intent(inout)         :: clock
       integer,          intent(out), optional :: rc
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:

clock
The object instance whose stop time to disable.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

37.5.18 ESMF_ClockStopTimeEnable - Enable an Clock's stop time


INTERFACE:

       subroutine ESMF_ClockStopTimeEnable(clock, stopTime, rc)
ARGUMENTS:
       type(ESMF_Clock), intent(inout)         :: clock
       type(ESMF_Time),  intent(in),  optional :: stopTime
       integer,          intent(out), optional :: rc
DESCRIPTION:

Enables a ESMF_Clock's stop time, allowing ESMF_ClockIsStopTime() to respect the stopTime.

The arguments are:

clock
The object instance whose stop time to enable.
[stopTime]
The stop time to set or reset.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

37.5.19 ESMF_ClockSyncToRealTime - Set Clock's current time to wall clock time


INTERFACE:

       subroutine ESMF_ClockSyncToRealTime(clock, rc)
ARGUMENTS:
       type(ESMF_Clock), intent(inout)         :: clock
       integer,          intent(out), optional :: rc
DESCRIPTION:

Sets a clock's current time to the wall clock time. It is accurate to the nearest second.

The arguments are:

clock
The object instance to be synchronized with wall clock time.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

37.5.20 ESMF_ClockValidate - Validate a Clock's properties


INTERFACE:

       subroutine ESMF_ClockValidate(clock, options, rc)
ARGUMENTS:
       type(ESMF_Clock),  intent(inout)         :: clock
       character (len=*), intent(in),  optional :: options
       integer,           intent(out), optional :: rc
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:

clock
ESMF_Clock to be validated.
[options]
Validation options are not yet supported.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

38 Alarm Class

38.1 Description

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.

38.2 Alarm Options

38.2.1 ESMF_AlarmListType

DESCRIPTION:
Specifies the characteristics of Alarms that populate a retrieved Alarm list.

Valid values are:

ESMF_ALARMLIST_ALL
All alarms.

ESMF_ALARMLIST_NEXTRINGING
Alarms that will ring before or at the next timestep.

ESMF_ALARMLIST_PREVRINGING
Alarms that rang at or since the last timestep.

ESMF_ALARMLIST_RINGING
Only ringing alarms.

38.3 Use and Examples

Alarms are used in conjunction with Clocks (see Section 37.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_MODE_REVERSE (see Section 37.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.
!-----------------------------------------------------------------------------

      ! ESMF Framework module
      use ESMF_Mod
      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

      ! initialize ESMF framework
      call ESMF_Initialize(defaultCalendar=ESMF_CAL_GREGORIAN, rc=rc)

38.3.1 Clock Initialization

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("The Clock", timeStep, startTime, stopTime, &
                               rc=rc)

38.3.2 Alarm Initialization

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("Example alarm 1", clock, &
                                  ringTime=alarmTime, 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)

38.3.3 Clock Advance and Alarm Processing

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))

        ! perform time step and get the number of any ringing alarms
        call ESMF_ClockAdvance(clock, ringingAlarmCount=ringingAlarmCount, &
                               rc=rc)

        call ESMF_ClockPrint(clock, "currTime string", 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)) 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)

            end if ! this alarm is ringing
          end do ! each ringing alarm
        endif ! ringing alarms
      end do ! timestep clock

38.3.4 Alarm and Clock Destruction

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

38.4 Restrictions and Future Work

  1. Alarm list allocation factor The alarm list within a clock is dynamically allocated automatically, 200 alarm references at a time. This constant is defined in both Fortran and C++ with a #define for ease of modification.

  2. Sticky alarm end times in reverse For sticky alarms, there is an implicit limitation that in order to properly reverse timestep through a ring end time, that time must have already been traversed in the forward direction. This is due to the fact that the Time Manager cannot predict when user code will call ESMF_AlarmRingerOff(). An error message will be logged when this limitation is not satisfied.

  3. Sticky alarm ring interval in reverse For repeating sticky alarms, it is currently assumed that the ringInterval is constant, so that only the time of the last call to ESMF_AlarmRingerOff() is saved. In ESMF_MODE_REVERSE, this information is used to turn sticky alarms back on. In a future release, ringIntervals will be allowed to be variable, by saving alarm state at every timestep.

38.5 Design and Implementation Notes

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.

38.6 Class API

38.6.1 ESMF_AlarmOperator(==) - Test if Alarm 1 is equal to Alarm 2


INTERFACE:

       interface operator(==)
       if (alarm1 == alarm2) then ... endif
                    OR
       result = (alarm1 == alarm2)
RETURN VALUE:
       logical :: result
ARGUMENTS:
       type(ESMF_Alarm), intent(in) :: alarm1
       type(ESMF_Alarm), intent(in) :: alarm2
DESCRIPTION:

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.

The arguments are:

alarm1
The first ESMF_Alarm in comparison.
alarm2
The second ESMF_Alarm in comparison.

38.6.2 ESMF_AlarmOperator(/=) - Test if Alarm 1 is not equal to Alarm 2


INTERFACE:

       interface operator(/=)
       if (alarm1 /= alarm2) then ... endif
                    OR
       result = (alarm1 /= alarm2)
RETURN VALUE:
       logical :: result
ARGUMENTS:
       type(ESMF_Alarm), intent(in) :: alarm1
       type(ESMF_Alarm), intent(in) :: alarm2
DESCRIPTION:

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.

The arguments are:

alarm1
The first ESMF_Alarm in comparison.
alarm2
The second ESMF_Alarm in comparison.

38.6.3 ESMF_AlarmCreate - Create a new ESMF Alarm


INTERFACE:

       ! Private name; call using ESMF_AlarmCreate()
       function ESMF_AlarmCreateNew(name, clock, ringTime, ringInterval, &
                                    stopTime, ringDuration, &
                                    ringTimeStepCount, &
                                    refTime, enabled, sticky, rc)
RETURN VALUE:
       type(ESMF_Alarm) :: ESMF_AlarmCreateNew
ARGUMENTS:
       character (len=*),       intent(in),  optional :: name
       type(ESMF_Clock),        intent(in)            :: 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 :: enabled
       logical,                 intent(in),  optional :: sticky
       integer,                 intent(out), optional :: rc
DESCRIPTION:

Creates and sets the initial values in a new ESMF_Alarm.

In ESMF_MODE_REVERSE (see Section 37.1), alarms ring in reverse, i.e., they begin ringing when they originally ended, and end ringing when they originally began.

This is a private method; invoke via the public overloaded entry point ESMF_AlarmCreate().

The arguments are:

[name]
The name for the newly created alarm. If not specified, a default unique name will be generated: "AlarmNNN" where NNN is a unique sequence number from 001 to 999.
clock
The clock with which to associate this newly created alarm.
[ringTime]
The ring time for a one-shot alarm or the first ring time for a repeating (interval) alarm. Must specify at least one of ringTime or ringInterval.
[ringInterval]
The ring interval for repeating (interval) alarms. If ringTime is not also specified (first ring time), it will be calculated as the clock's current time plus ringInterval. Must specify at least one of ringTime or ringInterval.
[stopTime]
The stop time for repeating (interval) alarms. If not specified, an interval alarm will repeat forever.
[ringDuration]
The absolute ring duration. If not sticky (see argument below), alarms rings for ringDuration, then turns itself off. Default is zero (unused). Mutually exclusive with ringTimeStepCount (below); used only if set to a non-zero duration and ringTimeStepCount is 1 (see below). See also ESMF_AlarmSticky(), ESMF_AlarmNotSticky().
[ringTimeStepCount]
The relative ring duration. If not sticky (see argument below), alarms rings for ringTimeStepCount, then turns itself off. Default is 1: a non-sticky alarm will ring for one clock time step. Mutually exclusive with ringDuration (above); used if ringTimeStepCount > 1. If ringTimeStepCount is 1 (default) and ringDuration is non-zero, ringDuration is used (see above), otherwise ringTimeStepCount is used. See also ESMF_AlarmSticky(), ESMF_AlarmNotSticky().
[refTime]
The reference (i.e. base) time for an interval alarm.
[enabled]
Sets the enabled state; default is on (true). If disabled, an alarm will not function at all. See also ESMF_AlarmEnable(), ESMF_AlarmDisable().
[sticky]
Sets the sticky state; default is on (true). If sticky, once an alarm is ringing, it will remain ringing until turned off manually via a user call to ESMF_AlarmRingerOff(). If not sticky, an alarm will turn itself off after a certain ring duration specified by either ringDuration or ringTimeStepCount (see above). There is an implicit limitation that in order to properly reverse timestep through a ring end time in ESMF_MODE_REVERSE, that time must have already been traversed in the forward direction. This is due to the fact that the Time Manager cannot predict when user code will call ESMF_AlarmRingerOff(). An error message will be logged when this limitation is not satisfied. See also ESMF_AlarmSticky(), ESMF_AlarmNotSticky().
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

38.6.4 ESMF_AlarmCreate - Create a copy of an existing ESMF Alarm


INTERFACE:

       ! Private name; call using ESMF_AlarmCreate()
       function ESMF_AlarmCreateCopy(alarm, rc)
RETURN VALUE:
       type(ESMF_Alarm) :: ESMF_AlarmCreateCopy
ARGUMENTS:
       type(ESMF_Alarm), intent(inout)         :: alarm
       integer,          intent(out), optional :: rc
DESCRIPTION:

Creates a copy of a given ESMF_Alarm.

This is a private method; invoke via the public overloaded entry point ESMF_AlarmCreate().

The arguments are:

alarm
The ESMF_Alarm to copy.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

38.6.5 ESMF_AlarmDestroy - Free all resources associated with an Alarm


INTERFACE:

       subroutine ESMF_AlarmDestroy(alarm, rc)
ARGUMENTS:
       type(ESMF_Alarm)               :: alarm
       integer, intent(out), optional :: rc
DESCRIPTION:

Releases all resources associated with this ESMF_Alarm.

The arguments are:

alarm
Destroy contents of this ESMF_Alarm.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

38.6.6 ESMF_AlarmDisable - Disable an Alarm


INTERFACE:

       subroutine ESMF_AlarmDisable(alarm, rc)
ARGUMENTS:
       type(ESMF_Alarm), intent(inout)         :: alarm
       integer,          intent(out), optional :: rc
DESCRIPTION:

Disables an ESMF_Alarm.

The arguments are:

alarm
The object instance to disable.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

38.6.7 ESMF_AlarmEnable - Enable an Alarm


INTERFACE:

       subroutine ESMF_AlarmEnable(alarm, rc)
ARGUMENTS:
       type(ESMF_Alarm), intent(inout)         :: alarm
       integer,          intent(out), optional :: rc
DESCRIPTION:

Enables an ESMF_Alarm to function.

The arguments are:

alarm
The object instance to enable.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

38.6.8 ESMF_AlarmGet - Get Alarm properties


INTERFACE:

       subroutine ESMF_AlarmGet(alarm, name, clock, ringTime, prevRingTime, &
                                ringInterval, stopTime, ringDuration, &
                                ringTimeStepCount, timeStepRingingCount, &
                                ringBegin, ringEnd, refTime, ringing, &
                                ringingOnPrevTimeStep, enabled, sticky, rc)
ARGUMENTS:
       type(ESMF_Alarm),        intent(inout)         :: alarm
       character (len=*),       intent(out), optional :: name
       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
       integer,                 intent(out), optional :: rc
DESCRIPTION:

Gets one or more of an ESMF_Alarm's properties.

The arguments are:

alarm
The object instance to query.
[name]
The name of this alarm.
[clock]
The associated clock.
[ringTime]
The ring time for a one-shot alarm or the next repeating alarm.
[prevRingTime]
The previous ring time.
[ringInterval]
The ring interval for repeating (interval) alarms.
[stopTime]
The stop time for repeating (interval) alarms.
[ringDuration]
The ring duration. Mutually exclusive with ringTimeStepCount (see below).
[ringTimeStepCount]
The number of time steps comprising the ring duration. Mutually exclusive with ringDuration (see above).
[timeStepRingingCount]
The number of time steps for which the alarm has been ringing thus far. Used internally for tracking ringTimeStepCount ring durations (see above). Mutually exclusive with ringBegin (see below). Increments in ESMF_MODE_FORWARD and decrements in ESMF_MODE_REVERSE; see Section 37.1.
[ringBegin]
The time when the alarm began ringing. Used internally for tracking ringDuration (see above). Mutually exclusive with timeStepRingingCount (see above).
[ringEnd]
The time when the alarm ended ringing. Used internally for re-ringing alarm in ESMF_MODE_REVERSE.
[refTime]
The reference (i.e. base) time for an interval alarm.
[ringing]
The current ringing state. See also ESMF_AlarmRingerOn(), ESMF_AlarmRingerOff().
[ringingOnPrevTimeStep]
The ringing state upon the previous time step. Same as ESMF_AlarmWasPrevRinging().
[enabled]
The enabled state. See also ESMF_AlarmEnable(), ESMF_AlarmDisable().
[sticky]
The sticky state. See also ESMF_AlarmSticky(), ESMF_AlarmNotSticky().

38.6.9 ESMF_AlarmIsEnabled - Check if Alarm is enabled


INTERFACE:

       function ESMF_AlarmIsEnabled(alarm, rc)
RETURN VALUE:
       logical :: ESMF_AlarmIsEnabled
ARGUMENTS:
       type(ESMF_Alarm), intent(inout)         :: alarm
       integer,          intent(out), optional :: rc
DESCRIPTION:

Check if ESMF_Alarm is enabled.

The arguments are:

alarm
The object instance to check for enabled state.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

38.6.10 ESMF_AlarmIsRinging - Check if Alarm is ringing


INTERFACE:

       function ESMF_AlarmIsRinging(alarm, rc)
RETURN VALUE:
       logical :: ESMF_AlarmIsRinging
ARGUMENTS:
       type(ESMF_Alarm), intent(inout)         :: alarm
       integer,          intent(out), optional :: rc
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:

alarm
The alarm to check for ringing state.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

38.6.11 ESMF_AlarmIsSticky - Check if Alarm is sticky


INTERFACE:

       function ESMF_AlarmIsSticky(alarm, rc)
RETURN VALUE:
       logical :: ESMF_AlarmIsSticky
ARGUMENTS:
       type(ESMF_Alarm), intent(inout)         :: alarm
       integer,          intent(out), optional :: rc
DESCRIPTION:

Check if alarm is sticky.

The arguments are:

alarm
The object instance to check for sticky state.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

38.6.12 ESMF_AlarmNotSticky - Unset an Alarm's sticky flag


INTERFACE:

       subroutine ESMF_AlarmNotSticky(alarm, ringDuration, &
                                      ringTimeStepCount, rc)
ARGUMENTS:
       type(ESMF_Alarm),        intent(inout)         :: alarm
       type(ESMF_TimeInterval), intent(in),  optional :: ringDuration
       integer,                 intent(in),  optional :: ringTimeStepCount
       integer,                 intent(out), optional :: rc
DESCRIPTION:

Unset an ESMF_Alarm's sticky flag; once alarm is ringing, it turns itself off after ringDuration.

The arguments are:

alarm
The object instance to unset sticky.
[ringDuration]
If not sticky, alarms rings for ringDuration, then turns itself off. Mutually exclusive with ringTimeStepCount (see below and full description in method ESMF_AlarmCreate() or ESMF_AlarmSet()).
[ringTimeStepCount]
If not sticky, alarms rings for ringTimeStepCount, then turns itself off. Mutually exclusive with ringDuration (see above and full description in method ESMF_AlarmCreate() or ESMF_AlarmSet()).
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

38.6.13 ESMF_AlarmPrint - Print out an Alarm's properties


INTERFACE:

       subroutine ESMF_AlarmPrint(alarm, options, rc)
ARGUMENTS:
       type(ESMF_Alarm),  intent(inout)         :: alarm
       character (len=*), intent(in),  optional :: options
       integer,           intent(out), optional :: rc
DESCRIPTION:

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.

Note: Many ESMF_<class>Print methods are implemented in C++. On some platforms/compilers there is a potential issue with interleaving Fortran and C++ output to stdout such that it doesn't appear in the expected order. If this occurs, the ESMF_IOUnitFlush() method may be used on unit 6 to get coherent output.

The arguments are:

alarm
ESMF_Alarm to be printed out.
[options]
Print options. If none specified, prints all alarm property values.
"clock" - print the associated clock's name.
"enabled" - print the alarm's ability to ring.
"name" - print the alarm's name.
"prevRingTime" - print the alarm's previous ring time.
"ringBegin" - print time when the alarm actually begins to ring.
"ringDuration" - print how long this alarm is to remain ringing.
"ringEnd" - print time when the alarm actually ends ringing.
"ringing" - print the alarm's current ringing state.
"ringingOnPrevTimeStep" - print whether the alarm was ringing immediately after the previous clock time step.
"ringInterval" - print the alarm's periodic ring interval.
"ringTime" - print the alarm's next time to ring.
"ringTimeStepCount" - print how long this alarm is to remain ringing, in terms of a number of clock time steps.
"refTime" - print the alarm's interval reference (base) time.
"sticky" - print whether the alarm must be turned off manually.
"stopTime" - print when alarm intervals end.
"timeStepRingingCount" - print the number of time steps the alarm has been ringing thus far.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

38.6.14 ESMF_AlarmRingerOff - Turn off an Alarm


INTERFACE:

       subroutine ESMF_AlarmRingerOff(alarm, rc)
ARGUMENTS:
       type(ESMF_Alarm), intent(inout)         :: alarm
       integer,          intent(out), optional :: rc
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_MODE_FORWARD (default) or ESMF_MODE_REVERSE. See Section 37.1.

The arguments are:

alarm
The object instance to turn off.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

38.6.15 ESMF_AlarmRingerOn - Turn on an Alarm


INTERFACE:

       subroutine ESMF_AlarmRingerOn(alarm, rc)
ARGUMENTS:
       type(ESMF_Alarm), intent(inout)         :: alarm
       integer,          intent(out), optional :: rc
DESCRIPTION:

Turn on an ESMF_Alarm; sets ringing state.

The arguments are:

alarm
The object instance to turn on.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

38.6.16 ESMF_AlarmSet - Set Alarm properties


INTERFACE:

       subroutine ESMF_AlarmSet(alarm, name, clock, ringTime, ringInterval, &
                                stopTime, ringDuration, ringTimeStepCount, &
                                refTime, ringing, enabled, sticky, rc)
ARGUMENTS:
       type(ESMF_Alarm),        intent(inout)         :: alarm
       character (len=*),       intent(in),  optional :: name
       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
       integer,                 intent(out), optional :: rc
DESCRIPTION:

Sets/resets one or more of the properties of an ESMF_Alarm that was previously initialized via ESMF_AlarmCreate().

The arguments are:

alarm
The object instance to set.
[name]
The new name for this alarm.
[clock]
Re-associates this alarm with a different clock.
[ringTime]
The next ring time for a one-shot alarm or a repeating (interval) alarm.
[ringInterval]
The ring interval for repeating (interval) alarms.
[stopTime]
The stop time for repeating (interval) alarms.
[ringDuration]
The absolute ring duration. If not sticky (see argument below), alarms rings for ringDuration, then turns itself off. Default is zero (unused). Mutually exclusive with ringTimeStepCount (below); used only if set to a non-zero duration and ringTimeStepCount is 1 (see below). See also ESMF_AlarmSticky(), ESMF_AlarmNotSticky().
[ringTimeStepCount]
The relative ring duration. If not sticky (see argument below), alarms rings for ringTimeStepCount, then turns itself off. Default is 1: a non-sticky alarm will ring for one clock time step. Mutually exclusive with ringDuration (above); used if ringTimeStepCount > 1. If ringTimeStepCount is 1 (default) and ringDuration is non-zero, ringDuration is used (see above), otherwise ringTimeStepCount is used. See also ESMF_AlarmSticky(), ESMF_AlarmNotSticky().
[refTime]
The reference (i.e. base) time for an interval alarm.
[ringing]
Sets the ringing state. See also ESMF_AlarmRingerOn(), ESMF_AlarmRingerOff().
[enabled]
Sets the enabled state. If disabled, an alarm will not function at all. See also ESMF_AlarmEnable(), ESMF_AlarmDisable().
[sticky]
Sets the sticky state. If sticky, once an alarm is ringing, it will remain ringing until turned off manually via a user call to ESMF_AlarmRingerOff(). If not sticky, an alarm will turn itself off after a certain ring duration specified by either ringDuration or ringTimeStepCount (see above). There is an implicit limitation that in order to properly reverse timestep through a ring end time in ESMF_MODE_REVERSE, that time must have already been traversed in the forward direction. This is due to the fact that the Time Manager cannot predict when user code will call ESMF_AlarmRingerOff(). An error message will be logged when this limitation is not satisfied. See also ESMF_AlarmSticky(), ESMF_AlarmNotSticky().
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

38.6.17 ESMF_AlarmSticky - Set an Alarm's sticky flag


INTERFACE:

       subroutine ESMF_AlarmSticky(alarm, rc)
ARGUMENTS:
       type(ESMF_Alarm), intent(inout)         :: alarm
       integer,          intent(out), optional :: rc
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_MODE_REVERSE, that time must have already been traversed in the forward direction. This is due to the fact that the Time Manager cannot predict when user code will call ESMF_AlarmRingerOff(). An error message will be logged when this limitation is not satisfied.

The arguments are:

alarm
The object instance to be set sticky.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

38.6.18 ESMF_AlarmValidate - Validate an Alarm's properties


INTERFACE:

       subroutine ESMF_AlarmValidate(alarm, options, rc)
ARGUMENTS:
       type(ESMF_Alarm),  intent(inout)         :: alarm
       character (len=*), intent(in),  optional :: options
       integer,           intent(out), optional :: rc
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:

alarm
ESMF_Alarm to be validated.
[options]
Validation options are not yet supported.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

38.6.19 ESMF_AlarmWasPrevRinging - Check if Alarm was ringing on the previous Clock timestep


INTERFACE:

       function ESMF_AlarmWasPrevRinging(alarm, rc)
RETURN VALUE:
       logical :: ESMF_AlarmWasPrevRinging
ARGUMENTS:
       type(ESMF_Alarm), intent(inout)         :: alarm
       integer,          intent(out), optional :: rc
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:

alarm
The object instance to check for previous ringing state.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

38.6.20 ESMF_AlarmWillRingNext - Check if Alarm will ring upon the next Clock timestep


INTERFACE:

       function ESMF_AlarmWillRingNext(alarm, timeStep, rc)
RETURN VALUE:
       logical :: ESMF_AlarmWillRingNext
ARGUMENTS:
       type(ESMF_Alarm),        intent(inout)         :: alarm
       type(ESMF_TimeInterval), intent(in),  optional :: timeStep
       integer,                 intent(out), optional :: rc
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:

alarm
The alarm to check for next ringing state.
[timeStep]
Optional timestep to use instead of the clock's.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

39 Config Class

39.1 Description

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.

Module ${\tt ESMF\_ConfigMod}$ is implemented in Fortran.

39.1.1 Package History

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.

39.1.2 Resource Files

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.

39.2 Use and Examples

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.

39.2.1 Variable Declarations

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

39.2.2 Creation of a Config

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)                    ! 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

39.2.3 How to Retrieve a Label with a Single Value

The first method for retrieving information from the Resource File takes advantage of the <label,value> relationship within the file and access the data in a dictionary-like manner. This is the simplest methodology, but it does imply the use of only one value per label in the Resource File.

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)

39.2.4 How to Retrieve a Label with Multiple Values

When there are multiple, mixed-typed values associated with a label, the values can be retrieved in two steps: 1) Use ESMF_ConfigFindLabel() to find the label in the Config class; 2) use ESMF_ConfigGetAttribute() without the optional 'label' argument to retrieve the values one at a time, reading from left to right in the record.

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 first filename
       call ESMF_ConfigGetAttribute(cf, fn2, rc=rc) !Step c) retrieve the second filename
       call ESMF_ConfigGetAttribute(cf, fn3, rc=rc) !Step d) retrieve the third filename

39.2.5 How to Retrieve a Table

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

39.2.6 Destruction of a Config

The work with the configuration file cf is finalized by call to ESMF_ConfigDestroy():

      call ESMF_ConfigDestroy(cf, rc) ! Destroy the Config

39.3 Class API

39.3.1 ESMF_ConfigCreate - Instantiate a Config object


INTERFACE:

       type(ESMF_Config) function ESMF_ConfigCreate( rc )
ARGUMENTS:
      integer,intent(out), optional              :: rc
DESCRIPTION:

Instantiates an ESMF_Config object for use in subsequent calls.

The arguments are:

[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

39.3.2 ESMF_ConfigDestroy - Destroy a Config object


INTERFACE:

     subroutine ESMF_ConfigDestroy( config, rc )
ARGUMENTS:
       type(ESMF_Config) :: config
       integer,intent(out), optional    :: rc
DESCRIPTION:

Destroys the config object.

The arguments are:

config
Already created ESMF_Config object.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

39.3.3 ESMF_ConfigFindLabel - Find a label


INTERFACE:

     subroutine ESMF_ConfigFindLabel( config, label, rc )
ARGUMENTS:
       type(ESMF_Config), intent(inout) :: config 
       character(len=*), intent(in)     :: label
       integer, intent(out), optional   :: rc
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:

config
Already created ESMF_Config object.
label
Identifying label.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors. Equals -1 if buffer could not be loaded, -2 if label not found, and -3 if invalid operation with index.

39.3.4 ESMF_ConfigGetAttribute - Get a value


INTERFACE:

        subroutine ESMF_ConfigGetAttribute( config, <value>, &
                                            label, default, rc )
ARGUMENTS:
        type(ESMF_Config), intent(inout)       :: config     
        <value argument>, see below for supported values
        character(len=*), intent(in), optional :: label 
        character(len=*), intent(in), optional :: default 
        integer, intent(out), optional         :: rc
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:

character(len=*), intent(out) :: value
real(ESMF_KIND_R4), intent(out) :: value
real(ESMF_KIND_R8), intent(out) :: value
integer(ESMF_KIND_I4), intent(out) :: value
integer(ESMF_KIND_I8), intent(out) :: value
logical, intent(out) :: value

The arguments are:

config
Already created ESMF_Config object.
<value argument>
Returned value.
[label]
Identifing label.
[default]
Default value if label is not found in config object.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

39.3.5 ESMF_ConfigGetAttribute - Get a list of values


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      
        integer, intent(in)                    :: count
        character(len=*), intent(in), optional :: label 
        character(len=*), intent(in), optional :: default 
        integer, intent(out), optional         :: rc
DESCRIPTION:

Gets a list of values from the config object.

Supported values for <value list argument> are:

real(ESMF_KIND_R4), intent(inout) :: valueList(:)
real(ESMF_KIND_R8), intent(inout) :: valueList(:)
integer(ESMF_KIND_I4), intent(inout) :: valueList(:)
integer(ESMF_KIND_I8), intent(inout) :: valueList(:)
logical, intent(inout) :: valueList(:)

The arguments are:

config
Already created ESMF_Config object.
<value list argument>
Returned value.
count
Number of returned values expected.
[label]
Identifing label.
[default]
Default value if label is not found in config object.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

39.3.6 ESMF_ConfigGetChar - Get a character


INTERFACE:

       subroutine ESMF_ConfigGetChar( config, value, label, default, rc )
ARGUMENTS:
       type(ESMF_Config), intent(inout)    :: config 
       character, intent(out)                 :: value
       character(len=*), intent(in), optional :: label   
       character, intent(in), optional        :: default
       integer, intent(out), optional         :: rc
DESCRIPTION:

Gets a character value from the config object.

The arguments are:

config
Already created ESMF_Config object.
value
Returned value.
[label]
Identifying label.
[default]
Default value if label is not found in configuration object.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

39.3.7 ESMF_ConfigGetDim - Get table sizes


INTERFACE:

 
     subroutine ESMF_ConfigGetDim( config, lineCount, columnCount, label, rc )
 
       implicit none
 
       type(ESMF_Config), intent(inout)       :: config    ! ESMF Configuration
       integer, intent(out)                   :: lineCount
       integer, intent(out)                   :: columnCount
 
       character(len=*), intent(in), optional :: label ! label (if present)
                                                       ! otherwise, current
                                                       ! line
 
       integer, intent(out), optional         :: rc     ! Error code
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:

config
Already created ESMF_Config object.
lineCount
Returned number of lines in the table.
columnCount
Returned maximum number of words in a table line.
[label]
Identifying label.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

39.3.8 ESMF_ConfigGetLen - Get the length of the line in words


INTERFACE:

     integer function ESMF_ConfigGetLen( config, label, rc )
ARGUMENTS:
       type(ESMF_Config), intent(inout)    :: config 
       character(len=*), intent(in), optional :: label
       integer, intent(out), optional :: rc
DESCRIPTION:

Gets the length of the line in words by counting words disregarding types. Returns the word count as an integer.

The arguments are:

config
Already created ESMF_Config object.
[label]
Identifying label. If not specified, use the current line.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

39.3.9 ESMF_ConfigLoadFile - Load resource file into memory


INTERFACE:

     subroutine ESMF_ConfigLoadFile( config, filename, delayout, unique, rc )
ARGUMENTS:
       type(ESMF_Config), intent(inout)        :: config     
       character(len=*), intent(in)               :: filename 
       type(ESMF_DELayout), intent(in), optional  :: delayout 
       logical, intent(in), optional              :: unique 
       integer, intent(out), optional             :: rc
DESCRIPTION:

Resource file with filename is loaded into memory.

The arguments are:

config
Already created ESMF_Config object.
filename
Configuration file name.
[delayout]
ESMF_DELayout associated with this config object.
[unique]
If specified as true, uniqueness of labels are checked and error code set if duplicates found.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

39.3.10 ESMF_ConfigNextLine - Find next line


INTERFACE:

     subroutine ESMF_ConfigNextLine( config, tableEnd, rc)
ARGUMENTS:
       type(ESMF_Config), intent(inout) :: config 
       logical, intent(out), optional :: tableEnd
       integer, intent(out), optional:: rc
DESCRIPTION:

Selects the next line (for tables).

The arguments are:

config
Already created ESMF_Config object.
[tableEnd]
If specifed as TRUE, end of table mark (::) is checked.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

39.3.11 ESMF_ConfigSetAttribute - Set a value


INTERFACE:

       subroutine ESMF_ConfigSetAttribute( config, <value argument>, &
                                           label, rc )
ARGUMENTS:
       type(ESMF_Config), intent(inout)             :: config     
       <value argument>, see below for supported values
       character(len=*), intent(in), optional       :: label 
       integer, intent(out), optional               :: rc
DESCRIPTION:

Sets a value in the config object.

Supported values for <value argument> are:

integer(ESMF_KIND_I4), intent(in) :: value

The arguments are:

config
Already created ESMF_Config object.
<value argument>
Value to set.
[label]
Identifying attribute label.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

39.3.12 ESMF_ConfigValidate - Validate a Config object


INTERFACE:

     subroutine ESMF_ConfigValidate(config, options, rc)
ARGUMENTS:
       type(ESMF_Config), intent(inout)         :: config 
       character (len=*), intent(in),  optional :: options
       integer, intent(out), optional           :: rc
DESCRIPTION:

Checks whether a config object is valid.

The arguments are:

config
ESMF_Config object to be validated.
[options]
If none specified: simply check that the buffer is not full and the pointers are within range. "unusedAttributes" - Report to the default logfile all attributes not retrieved via a call to ESMF_ConfigGetAttribute() or ESMF_ConfigGetChar(). The attribute name (label) will be logged via ESMF_LogErr with the WARNING log message type. For an array-valued attribute, retrieving at least one value via ESMF_ConfigGetAttribute() or ESMF_ConfigGetChar() constitutes being "used."
[rc]
Return code; equals ESMF_SUCCESS if there are no errors. Equals ESMF_RC_ATTR_UNUSED if any unused attributes are found with option "unusedAttributes" above.

40 LogErr Class

40.1 Description

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 LogErr 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.

LogErr 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 halt the program on an error or on a warning by using the ESMF_LogSet() method with the halt property. When the halt property is set to ESMF_LOG_HALTWARNING, the program will stop on any and all warning or errors. When the halt property is set to ESMF_LOG_HALTERROR, the program will only halt only on errors. Lastly, the user can choose to never halt by setting the halt property to ESMF_LOG_HALTNEVER; this is the default.

LogErr will automatically put the PET number into the Log. Also, the user can either specify ESMF_LOG_SINGLE which writes all the entries to a single Log or ESMF_LOG_MULTI which writes entries to multiple Logs according to the PET number. To distinguish Logs from each other when using ESMF_LOG_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_LOG_NONE is provided to switch off the LogErr capability. All the LogErr methods have no effect in the ESMF_LOG_NONE mode.

Other options that are planned for LogErr are to adjust the verbosity of ouput, and to optionally write to stdout instead of file(s).

40.2 LogErr Options

40.2.1 ESMF_HaltType

DESCRIPTION:
Specifies when to halt -- e.g., never, when a warning is issued, or when an error message is encountered.

Valid values are:

ESMF_LOG_HALTNEVER
Never halt. (Default.)
ESMF_LOG_HALTWARNING
Halt when either a warning or an error message is issued.
ESMF_LOG_HALTERROR
Halt only when an error message is issued.

40.2.2 ESMF_MsgType

DESCRIPTION:
Specifies what message level -- e.g., informational, warning, error -- will be written to log files.

Valid values are:

ESMF_LOG_INFO
Issue informational, warning, and error messages. (Default.)
ESMF_LOG_WARNING
Issue warning and error messages.
ESMF_LOG_ERROR
Only issue error messages.

40.2.3 ESMF_LogType

DESCRIPTION:
Specifies a single log file, multiple log files (one per PET), or no log files.

Valid values are:

ESMF_LOG_SINGLE
Use a single log file, combining messages from all of the PETs. Not supported on some platforms.
ESMF_LOG_MULTI
Use multiple log files -- one per PET. (Default.)
ESMF_LOG_NONE
Do not issue messages to a log file.

40.3 Use and Examples

By default ESMF_Initialize() opens a default Log in ESMF_LOG_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 logtype property to ESMF_LOG_SINGLE or ESMF_LOG_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 would include an option to either truncate or append to the Log file.

In all cases where a Log is opened, a unit number is assigned to a specific Log. A Log is assigned the lowest available unit number starting with 11. If a unit number is occupied, the next higher unit number is checked using the Fortran "inquire" method. The process repeats until a free unit number is found or when the unit number reaches ESMF_LOG_UPPER in which case an error is returned. As a result, the user should always check for free numbers using Fortran's "inquire" to prevent potential unit number conflicts. In the future we anticipate supporting an option in which a desired unit number can be passed in.

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).

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 logtype property set to ESMF_LOG_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
!-----------------------------------------------------------------------------

! 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_Mod
    implicit none
    
    ! return variables
    integer :: rc1, rc2, rc3, rcToTest, allocRcToTest
    type(ESMF_LOG) :: alog  ! a log object that is not the default log
    type(ESMF_LogType) :: defaultLogtype
    type(ESMF_Time) :: time
    integer, pointer :: intptr(:)

40.3.1 Default Log

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(rc=rc1, defaultlogtype=ESMF_LOG_MULTI)

    ! LogWrite 
    call ESMF_LogWrite("Log Write 2", ESMF_LOG_INFO, rc=rc2)

    ! LogMsgSetError
    call ESMF_LogMsgSetError(ESMF_FAILURE, "Convergence failure", &
                             rcToReturn=rc2)
    ! LogMsgFoundError
    call ESMF_TimeSet(time, calendarType=ESMF_CAL_NOCALENDAR)
    call ESMF_TimeSyncToRealTime(time, rcToTest)
    if (ESMF_LogMsgFoundError(rcToTest, "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_LogMsgFoundAllocError(allocRcToTest, "integer array", &
                                   rcToReturn=rc2)) then
        ! Error during allocation.  The previous call will have logged already
        ! an error message into the log.
    endif
    deallocate(intptr)

40.3.2 User Created Log

This example shows how to use a user created Log. This example uses cpp macros.

    ! Open a Log named "Testlog.txt" associated with alog.
    call ESMF_LogOpen(alog, "TestLog.txt", rc=rc1)

    ! LogWrite; ESMF_CONTEXT expands into __LINE__,ESMF_FILENAME,ESMF_METHOD
    call ESMF_LogWrite("Log Write 2", ESMF_LOG_INFO, ESMF_CONTEXT, &
                       log=alog, rc=rc2)

    ! LogMsgSetError; ESMF_CONTEXT expands into
    !   __LINE__,ESMF_FILENAME,ESMF_METHOD
    call ESMF_LogMsgSetError(ESMF_FAILURE, "Interpolation Failure", &
                             ESMF_CONTEXT, rcToReturn=rc2, log=alog)

40.3.3 Get and Set

This example shows how to use Get and Set routines, on both the default Log and the user created Log from the previous examples.

    ! 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(logtype=defaultLogtype, 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, halt=ESMF_LOG_HALTERROR, rc=rc2)

    ! Close the user log.
    call ESMF_LogClose(alog, rc3)

    ! Finalize ESMF to close the default log
    call ESMF_Finalize(rc=rc1)

40.4 Restrictions and Future Work

  1. Line, file and method are only available when using the C preprocessor Message writing methods are expanded using the ESMF macro ESMF_CONTEXT that adds the predefined symbolic constants __LINE__ and __FILE__ (or the ESMF constant ESMF_FILENAME if defined) and the ESMF constant ESMF_METHOD to the argument list. Using these constants, we can associate a file name, line number and method name with the message. If the CPP preprocessor is not used, this expansion will not be done and hence the ESMF macro ESMF_CONTEXT can not be used, leaving the file name, line number and method out of the Log text.

  2. Get and set methods are partially implemented. Currently, the ESMF_LogGet() and ESMF_LogSet() methods are partially implemented.

  3. Log only appends entries. All writing to the Log is appended rather than overwriting the Log. Future enhancements include the option to either append to an existing Log or overwrite the existing Log.

  4. Avoiding conflicts with the default Log. The private methods ESMF_LogInitialize() and ESMF_LogFinalize() are called during ESMF_Initialize() and ESMF_Finalize() respectively, so they do not need to be called if the default Log is used. If a new Log is required, ESMF_LogOpen() is used with a new Log object passed in so that there are no conflicts with the default Log.

  5. ESMF_LOG_SINGLE does not work properly. When the ESMF_LogType is set to ESMF_LOG_SINGLE, different system may behave differently. The log messages from some processors may be lost or overwritten by other processors. Users are advised not to use this mode. The MPI-based I/O will be implemented to fix the problem in the future release.

40.5 Design and Implementation Notes

  1. The Log class was implemented in Fortran and uses the Fortran I/O libraries when the class methods are called from Fortran. The C/C++ Log methods use the Fortran I/O library by calling utility functions that are written in Fortran. These utility functions call the standard Fortran write, open and close functions. At initialization an ESMF_LOG is created. The ESMF_LOG stores information for a specific Log file. When working with more than one Log file, multiple ESMF_LOG's are required (one ESMF_LOG for each Log file). For each Log, a handle is returned through the ESMF_LogInitialize method for the default log or ESMF_LogOpen for a user created log. The user can specify single or multi logs by setting the logtype property in the ESMF_LogInitialize or ESMF_Open method to ESMF_LOG_SINGLE or ESMF_LOG_MULTI. Similarly, the user can set the defaultlogtype property for the default Log with the ESMF_Initialize method call. The logtype 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.

    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).

40.6 Object Model

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.

\includegraphics[]{Log_obj}

40.7 Class API

40.7.1 ESMF_LogClose - Close Log file(s)


INTERFACE:

     subroutine ESMF_LogClose(log, rc)
ARGUMENTS:
     type(ESMF_Log)	                                        :: log
     integer, intent(out),optional                               :: rc
DESCRIPTION:

This routine closes the file(s) associated with the log.

The arguments are:

log
An ESMF_Log object.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

40.7.2 ESMF_LogFlush - Flushes the Log file(s)


INTERFACE:

 	subroutine ESMF_LogFlush(log,rc)
ARGUMENTS:
         type(ESMF_Log), target,optional				:: log
 	integer, intent(out),optional		                :: rc
DESCRIPTION:

This subroutine flushes the ESMF_Log buffer to its associated file.

The arguments are:

[log]
An optional ESMF_Log object that can be used instead of the default Log.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

40.7.3 ESMF_LogFoundAllocError - Check Fortran status for allocation error


INTERFACE:

 	function ESMF_LogFoundAllocError(statusToCheck, line, file, & 
                                          method, rcToReturn,log)
RETURN VALUE:
 	logical                                     ::ESMF_LogFoundAllocError
ARGUMENTS:
  	
 	integer, intent(in)                         :: statusToCheck
 	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	    :: log
DESCRIPTION:

This function returns a logical 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 line, file and method. Additionally, the statusToCheck will be converted to a rcToReturn.

The arguments are:

statusToCheck
Fortran allocation status to check.
[line]
Integer source line number. Expected to be set by using the preprocessor macro __LINE__ macro.
[file]
User-provided source file name.
[method]
User-provided method string.
[rcToReturn]
If specified, set the rcToReturn value to ESMF_RC_MEM which is the error code for a memory allocation eror.
[log]
An optional ESMF_Log object that can be used instead of the default Log.

40.7.4 ESMF_LogFoundDeallocError - Check Fortran status for deallocation error


INTERFACE:

 	function ESMF_LogFoundDeallocError(statusToCheck, line, file, & 
                                          method, rcToReturn,log)
RETURN VALUE:
 	logical                                     ::ESMF_LogFoundDeallocError
ARGUMENTS:
  	
 	integer, intent(in)                         :: statusToCheck
 	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	    :: log
DESCRIPTION:

This function returns a logical 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 line, file and method. Additionally, the statusToCheck will be converted to a rcToReturn.

The arguments are:

statusToCheck
Fortran allocation status to check.
[line]
Integer source line number. Expected to be set by using the preprocessor macro __LINE__ macro.
[file]
User-provided source file name.
[method]
User-provided method string.
[rcToReturn]
If specified, set the rcToReturn value to ESMF_RC_MEM which is the error code for a memory allocation eror.
[log]
An optional ESMF_Log object that can be used instead of the default Log.

40.7.5 ESMF_LogFoundError - Check ESMF return code for error


INTERFACE:

 	function ESMF_LogFoundError(rcToCheck, line, file, method,& 
 	         rcToReturn, log)
RETURN VALUE:
 	logical                                         ::ESMF_LogFoundError
ARGUMENTS:
  	
 	integer, intent(in)                             :: rcToCheck
 	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), target, optional  :: log
DESCRIPTION:

This function returns a logical true for ESMF return codes that indicate an error. A predefined error message will added to the ESMF_Log along with line, file and method. Additionally, rcToReturn will be set to rcToCheck.

The arguments are:

rcToCheck
Return code to check.
[line]
Integer source line number. Expected to be set by using the preprocessor macro __LINE__ macro.
[file]
User-provided source file name.
[method]
User-provided method string.
[rcToReturn]
If specified, copy the rcToCheck value to rc. This is not the return code for this function; it allows the calling code to do an assignment of the error code at the same time it is testing the value.
[log]
An optional ESMF_Log object that can be used instead of the default Log.

40.7.6 ESMF_LogMsgFoundAllocError - Check Fortran status for allocation

error and write message


INTERFACE:

 	function ESMF_LogMsgFoundAllocError(statusToCheck,msg,line,file, &
                                             method,rcToReturn,log)
RETURN VALUE:
 	logical                                     ::ESMF_LogMsgFoundAllocError
ARGUMENTS:
  	
 	integer, intent(in)                         :: statusToCheck
 	character(len=*), intent(in)                :: 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	    :: log
DESCRIPTION:

This function returns a logical 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:

statusToCheck
Fortran allocation status to check.
msg
User-provided message string.
[line]
Integer source line number. Expected to be set by using the preprocessor macro __LINE__ macro.
[file]
User-provided source file name.
[method]
User-provided method string.
[rcToReturn]
If specified, set the rcToReturn value to ESMF_RC_MEM which is the error code for a memory allocation eror.
[log]
An optional ESMF_Log object that can be used instead of the default Log.

40.7.7 ESMF_LogMsgFoundDeallocError - Check Fortran status for allocation

error and write message


INTERFACE:

 	function ESMF_LogMsgFoundDeallocError(statusToCheck,msg,line,file, &
                                             method,rcToReturn,log)
RETURN VALUE:
 	logical                                     ::ESMF_LogMsgFoundDeallocError
ARGUMENTS:
  	
 	integer, intent(in)                         :: statusToCheck
 	character(len=*), intent(in)                :: 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	    :: log
DESCRIPTION:

This function returns a logical 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:

statusToCheck
Fortran allocation status to check.
msg
User-provided message string.
[line]
Integer source line number. Expected to be set by using the preprocessor macro __LINE__ macro.
[file]
User-provided source file name.
[method]
User-provided method string.
[rcToReturn]
If specified, set the rcToReturn value to ESMF_RC_MEM which is the error code for a memory allocation eror.
[log]
An optional ESMF_Log object that can be used instead of the default Log.

40.7.8 ESMF_LogMsgFoundError - Check ESMF return code for error and write message


INTERFACE:

 	function ESMF_LogMsgFoundError(rcToCheck, msg, line, file, method, &
                                        rcToReturn, log)
RETURN VALUE:
 	logical                                         ::ESMF_LogMsgFoundError
ARGUMENTS:
  	
 	integer, intent(in)                             :: rcToCheck
 	character(len=*), intent(in)                    :: 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), target, optional    :: log
DESCRIPTION:

This function returns a logical 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:

rcToCheck
Return code to check.
msg
User-provided message string.
[line]
Integer source line number. Expected to be set by using the preprocessor macro __LINE__ macro.
[file]
User-provided source file name.
[method]
User-provided method string.
[rcToReturn]
If specified, copy the rcToCheck value to rc. This is not the return code for this function; it allows the calling code to do an assignment of the error code at the same time it is testing the value.
[log]
An optional ESMF_Log object that can be used instead of the default Log.

40.7.9 ESMF_LogMsgSetError - Set ESMF return code for error and write msg


INTERFACE:

 	subroutine ESMF_LogMsgSetError(rcValue, msg, line, file, method, &
                                        rcToReturn, log)
ARGUMENTS:
  	
 	integer, intent(in)                             :: rcValue
 	character(len=*), intent(in)                    :: 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), target, optional    :: log
DESCRIPTION:

This subroutine sets the rcToReturn value to rcValue 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:

rcValue
rc value for set
msg
User-provided message string.
[line]
Integer source line number. Expected to be set by using the preprocessor macro __LINE__ macro.
[file]
User-provided source file name.
[method]
User-provided method string.
[rcToReturn]
If specified, copy the rcValue value to rcToreturn. This is not the return code for this function; it allows the calling code to do an assignment of the error code at the same time it is testing the value.
[log]
An optional ESMF_Log object that can be used instead of the default Log.

40.7.10 ESMF_LogOpen - Open Log file(s)


INTERFACE:

     subroutine ESMF_LogOpen(log, filename, logtype, rc)
ARGUMENTS:
     type(ESMF_Log)			                :: log
     character(len=*)			                :: filename
     type(ESMF_LogType), intent(in),optional             :: logtype  
     integer, intent(out),optional	                :: rc
DESCRIPTION:

This routine opens a file with filename and associates it with the ESMF_Log. This is only used when the user does not want to use the default Log.

The arguments are:

log
An ESMF_Log object.
filename
Name of file. Maximum length 58 characters to allow for the PET number to be added and keep the total file name length under 64 characters.
[logtype]
Set the logtype. See section 40.2.3 for a list of valid options. If not specified, defaults to ESMF_LOG_MULTI.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

40.7.11 ESMF_LogSet - Set Log parameters


INTERFACE:

 	subroutine ESMF_LogSet(log,verbose,flush,rootOnly,halt, &
                                stream,maxElements,errorMask,rc)
ARGUMENTS:
  	
 	type(ESMF_Log), target,optional                         :: log
 	logical, intent(in),optional			        :: verbose
 	logical, intent(in),optional			        :: flush
 	logical, intent(in),optional			        :: rootOnly
 	type(ESMF_HaltType), intent(in),optional                :: halt
 	integer, intent(in),optional			        :: stream  
 	integer, intent(in),optional			        :: maxElements
 	integer, intent(in),optional			        :: errorMask(:)
 	integer, intent(out),optional			        :: rc
DESCRIPTION:

This subroutine sets the properties for the Log object.

The arguments are:

[log]
An optional ESMF_Log object that can be used instead of the default Log.
[verbose]
Verbose flag.
[rootOnly]
Root only flag.
[halt]
Halt definition, with the following valid values:
ESMF_LOG_HALTWARNING;
ESMF_LOG_HALTERROR;
ESMF_LOG_HALTNEVER.
[stream]
The type of stream, with the following valid values and meanings:
0 free;
1 preordered.
[maxElements]
Maximum number of elements in the Log.
[errorMask]
List of error codes that will not be logged as errors.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

40.7.12 ESMF_LogWrite - Write to Log file(s)


INTERFACE:

 	recursive subroutine ESMF_LogWrite(msg,MsgType,line,file,method,log,rc)
ARGUMENTS:
 	character(len=*), intent(in)                :: msg
 	type(ESMF_MsgType), intent(in)              :: msgtype
 	integer, intent(in), optional               :: line
 	character(len=*), intent(in), optional      :: file
 	character(len=*), intent(in), optional	    :: method
 	type(ESMF_Log),target,optional   	    :: log
 	integer, intent(out),optional		    :: rc
DESCRIPTION:

This subroutine writes to the file associated with an ESMF_Log. A message is passed in along with the msgtype, 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:

msg
User-provided message string.
msgtype
The type of message. See Section 40.2.2 for possible values.
[line]
Integer source line number. Expected to be set by using the preprocessor macro __LINE__ macro.
[file]
User-provided source file name.
[method]
User-provided method string.
[log]
An optional ESMF_Log object that can be used instead of the default Log.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

41 DELayout Class

41.1 Description

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.

41.2 DELayout Options

41.2.1 ESMF_DePinFlag

DESCRIPTION:
Specifies which VM resource DEs are pinned to - i.e. PETs or VASs.

Valid values are:

ESMF_DE_PIN_PET
Pin DEs against PETs. This means that even if a group of PETs in the VM are sharing a common virtual address space (VAS), DEs cannot be shared between PETs, but must be serviced by the specific PET they are pinned to.
ESMF_DE_PIN_VAS
Pin DEs against VASs. DEs may be serviced by any PET that is executing within the virtual address space (VAS) the DE is pinned to.

41.3 Use and Examples

The following examples demonstrate how to create, use and destroy DELayout objects.

41.3.1 Default DELayout

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

41.3.2 DELayout with specified number of DEs

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 3
The 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

41.3.3 DELayout with computational and communication weights

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.

41.3.4 DELayout from petMap

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)

41.3.5 DELayout from petMap with multiple DEs per PET

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)

41.3.6 Working with a DELayout - simple 1-to-1 DE to PET mapping

The simplest case is a DELayout with as many DEs as PETs where each DE is against a separate PET. This of course 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 codes assume this mapping. The following example code shows how a DELayout can be queried about its mapping.

  delayout = ESMF_DELayoutCreate(rc=rc)

  call ESMF_DELayoutGet(delayout, oneToOneFlag=oneToOneFlag, rc=rc)
  if (rc /= ESMF_SUCCESS) finalrc=rc
  if (.not. oneToOneFlag) then
    ! handle the unexpected case of general DE to PET mapping
  endif
  allocate(localDeList(1))
  call ESMF_DELayoutGet(delayout, localDeList=localDeList, rc=rc)
  if (rc /= ESMF_SUCCESS) finalrc=rc
  myDe = localDeList(1)
  deallocate(localDeList)

41.3.7 Working with a DELayout - general DE to PET mapping

In general a DELayout may describe a DE to PET mapping that is not 1-to-1. The following example shows how code can be written in a general form that will work on all PETs for DELayouts with general or 1-to-1 DE to PET mapping.

  delayout = ESMF_DELayoutCreate(deCount=petCount+2, rc=rc)

  call ESMF_DELayoutGet(delayout, localDeCount=localDeCount, rc=rc)
  if (rc /= ESMF_SUCCESS) finalrc=rc
  allocate(localDeList(localDeCount))
  call ESMF_DELayoutGet(delayout, localDeList=localDeList, rc=rc)
  if (rc /= ESMF_SUCCESS) finalrc=rc
  do i=1, localDeCount
    workDe = localDeList(i)
!    print *, "I am PET", localPET, " and I am working on DE ", workDe
  enddo
  deallocate(localDeList)

41.3.8 Work queue dynamic load balancing

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, dePinFlag=ESMF_DE_PIN_VAS,&
    rc=rc)

  call ESMF_DELayoutGet(delayout, vasLocalDeCount=localDeCount, rc=rc)
  if (rc /= ESMF_SUCCESS) finalrc=rc
  allocate(localDeList(localDeCount))
  call ESMF_DELayoutGet(delayout, vasLocalDeList=localDeList, rc=rc)
  if (rc /= ESMF_SUCCESS) finalrc=rc
  do i=1, localDeCount
    workDe = localDeList(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_DELAYOUT_SERVICE_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(localDeList)

41.4 Restrictions and Future Work

41.5 Design and Implementation Notes

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.

41.6 Class API

41.6.1 ESMF_DELayoutCreate - Create DELayout object


INTERFACE:

   ! Private name; call using ESMF_DELayoutCreate()
   function ESMF_DELayoutCreateDefault(deCount, deGrouping, dePinFlag, petList, &
     vm, rc)
ARGUMENTS:
     integer,                      intent(in), optional  :: deCount
     integer, target,              intent(in), optional  :: deGrouping(:)
     type(ESMF_DePinFlag),         intent(in), optional  :: dePinFlag
     integer, target,              intent(in), optional  :: petList(:)
     type(ESMF_VM),                intent(in), optional  :: vm
     integer,                      intent(out),optional  :: rc
RETURN VALUE:
     type(ESMF_DELayout) :: ESMF_DELayoutCreateDefault
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:

[deCount]
Number of DEs to be provided by the created DELayout. By default the number of DEs equals the number of PETs in the associated VM context. Specifying a deCount smaller than the number of PETs will result in unassociated PETs. This may be used to share VM resources between DELayouts within the same ESMF component. Specifying a deCount greater than the number of PETs will result in multiple DE to PET mapping.
[deGrouping]
This optional argument must be of size deCount. Its content assigns a DE group index to each DE of the DELayout. A group index of -1 indicates that the associated DE isn't member of any particular group. The significance of DE groups is that all the DEs belonging to a certain group will be mapped against the same PET. This does not, however, mean that DEs belonging to different DE groups must be mapped to different PETs.
[dePinFlag]
This flag specifies which type of resource DEs are pinned to. The default is to pin DEs to PETs. Alternatively it is also possible to pin DEs to VASs. See section 41.2.1 for a list of valid pinning options.
[petList]
List specifying PETs to be used by this DELayout. This can be used to control the PET overlap between DELayouts within the same ESMF component. It is erroneous to specify PETs that are not within the provided VM context. The default is to include all the PETs of the VM.
[vm]
Optional ESMF_VM object of the current context. Providing the VM of the current context will lower the method's overhead.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

41.6.2 ESMF_DELayoutCreate - Create DELayout from petMap


INTERFACE:

   ! Private name; call using ESMF_DELayoutCreate()
   function ESMF_DELayoutCreateFromPetMap(petMap, dePinFlag, vm, rc)
ARGUMENTS:
     integer,                      intent(in)            :: petMap(:)
     type(ESMF_DePinFlag),         intent(in), optional  :: dePinFlag
     type(ESMF_VM),                intent(in), optional  :: vm
     integer,                      intent(out),optional  :: rc
RETURN VALUE:
     type(ESMF_DELayout) :: ESMF_DELayoutCreateFromPetMap
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:

petMap
List specifying the DE-to-PET mapping. The list elements correspond to DE 0, 1, 2, ... and map against the specified PET of the VM context. The size of the petMap argument determines the number of DEs in the created DELayout. It is erroneous to specify a PET identifier that lies outside the VM context.
[dePinFlag]
This flag specifies which type of resource DEs are pinned to. The default is to pin DEs to PETs. Alternatively it is also possible to pin DEs to VASs. See section 41.2.1 for a list of valid pinning options.
[vm]
Optional ESMF_VM object. The VM of the current context is the typical and default value.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

41.6.3 ESMF_DELayoutCreate - Create DELayout with weight hints


INTERFACE:

   ! Private name; call using ESMF_DELayoutCreate()
   function ESMF_DELayoutCreateHintWeights(deCount, compWeights, commWeights, &
     deGrouping, dePinFlag, petList, vm, rc)
ARGUMENTS:
     integer,                      intent(in), optional  :: deCount
     integer,                      intent(in)            :: compWeights(:)
     integer,                      intent(in)            :: commWeights(:,:)
     integer, target,              intent(in), optional  :: deGrouping(:)
     type(ESMF_DePinFlag),         intent(in), optional  :: dePinFlag
     integer, target,              intent(in), optional  :: petList(:)
     type(ESMF_VM),                intent(in), optional  :: vm
     integer,                      intent(out),optional  :: rc
RETURN VALUE:
     type(ESMF_DELayout) :: ESMF_DELayoutCreateHintWeights
DESCRIPTION:

Create an ESMF_DELayout on the basis of computational and communication weights. In addition this call provides control over the number of DEs, DE domains, DE pinning and the PETs to map against.

The arguments are:

[deCount]
Number of DEs to be provided by the created DELayout. By default the number of DEs equals the number of PETs in the associated VM context. Specifying a deCount smaller than the number of PETs will result in unassociated PETs. This may be used to share VM resources between DELayouts within the same ESMF component. Specifying a deCount greater than the number of PETs will result in multiple DE to PET mapping.
compWeights
This argument provides the computational weight hint. The compWeights list must contain at least deCount elements and specifies a relative measure of the computational weight for each DE in form of an integer number. The weights are a relative measure and only meaningful when compared to weights of the same DELayout. (UNIMPLEMENTED!)
commWeights
This argument provides the communication weight hint. commWeights is a 2D array and must contain at least deCount elements in each dimension. The element indices correspond to the DEs of the DELayout and each element specifies a relative communication weight for a DE pair. The commWeight matrix must be symmetric and diagonal elements are ignored. The weights are a relative measure and only meaningful when compared to weights of the same DELayout. (UNIMPLEMENTED!)
[dePinFlag]
This flag specifies which type of resource DEs are pinned to. The default is to pin DEs to PETs. Alternatively it is also possible to pin DEs to VASs. See section 41.2.1 for a list of valid pinning options.
[petList]
List specifying PETs to be used by this DELayout. This can be used to control the PET overlap between DELayouts within the same ESMF component. It is erroneous to specify PETs that are not within the provided VM context. The default is to include all the PETs of the VM.
[vm]
Optional ESMF_VM object of the current context. Providing the VM of the current context will lower the method's overhead.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

41.6.4 ESMF_DELayoutDestroy - Destroy DELayout object


INTERFACE:

   subroutine ESMF_DELayoutDestroy(delayout, rc)
ARGUMENTS:
     type(ESMF_DELayout),  intent(inout)           :: delayout
     integer,              intent(out),  optional  :: rc
DESCRIPTION:

Destroy an ESMF_DELayout object.

The arguments are:

delayout
ESMF_DELayout object to be destroyed.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

41.6.5 ESMF_DELayoutGet - Get DELayout internals


INTERFACE:

   subroutine ESMF_DELayoutGet(delayout, vm, deCount, petMap, vasMap, &
     compCapacity, commCapacity, oneToOneFlag, dePinFlag, &
     localDeCount, localDeList, vasLocalDeCount, vasLocalDeList, rc)
ARGUMENTS:
     type(ESMF_DELayout),          intent(in)              :: delayout
     type(ESMF_VM),                intent(out),  optional  :: vm
     integer,                      intent(out),  optional  :: deCount
     integer, target,              intent(out),  optional  :: petMap(:)
     integer, target,              intent(out),  optional  :: vasMap(:)
     integer, target,              intent(out),  optional  :: compCapacity(:)
     integer, target,              intent(out),  optional  :: commCapacity(:,:)
     logical,                      intent(out),  optional  :: oneToOneFlag
     type(ESMF_DePinFlag),         intent(out),  optional  :: dePinFlag
     integer,                      intent(out),  optional  :: localDeCount
     integer, target,              intent(out),  optional  :: localDeList(:)
     integer,                      intent(out),  optional  :: vasLocalDeCount
     integer, target,              intent(out),  optional  :: vasLocalDeList(:)
     integer,                      intent(out),  optional  :: rc
DESCRIPTION:

Access to DELayout information.

The arguments are:

delayout
Queried ESMF_DELayout object.
[vm]
Upon return this holds the ESMF_VM object on which the delayout is defined.
[deCount]
Upon return this holds the total number of DEs.
[petMap]
Upon return this holds the list of PETs against which the DEs are mapped. The petMap argument must at least be of size deCount.
[vasMap]
Upon return this holds the list of VASs against which the DEs are mapped. The vasMap argument must at least be of size deCount.
[compCapacity]
Upon return this holds a relative measure of the computational capacity for each DE. The compCapacity argument must at least be of size deCount.
[commCapacity]
Upon return this holds a relative measure of the communication capacity for each pair of DEs. The commCapacity argument is a 2D array where each dimension must at least be of size deCount.
[oneToOneFlag]
Upon return this holds .TRUE. if the specified ESMF_DELayout describes a 1-to-1 mapping between DEs and PETs, .FALSE. otherwise.
[dePinFlag]
Upon return this flag will indicate the type of DE pinning. See section 41.2.1 for a list of valid pinning options.
[localDeCount]
Upon return this holds the number of DEs associated with the local PET.
[localDeList]
Upon return this holds the list of DEs associated with the local PET. The provided argument must at least be of size localDeCount.
[vasLocalDeCount]
Upon return this holds the number of DEs associated with the local VAS.
[vasLocalDeList]
Upon return this holds the list of DEs associated with the local VAS. The provided argument must at least be of size vasLocalDeCount.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

41.6.6 ESMF_DELayoutPrint - Print DELayout internals


INTERFACE:

   subroutine ESMF_DELayoutPrint(delayout, options, rc)
ARGUMENTS:
     type(ESMF_DELayout),  intent(in)              :: delayout
     character(len=*),     intent(in),   optional  :: options
     integer,              intent(out),  optional  :: rc
DESCRIPTION:

Prints internal information about the specified ESMF_DELayout object to stdout.

Note: Many ESMF_<class>Print methods are implemented in C++. On some platforms/compilers there is a potential issue with interleaving Fortran and C++ output to stdout such that it doesn't appear in the expected order. If this occurs, the ESMF_IOUnitFlush() method may be used on unit 6 to get coherent output.

The arguments are:

delayout
Specified ESMF_DELayout object.
[options]
Print options are not yet supported.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

41.6.7 ESMF_DELayoutServiceComplete - Close service window


INTERFACE:

   recursive subroutine ESMF_DELayoutServiceComplete(delayout, de, rc)
ARGUMENTS:
     type(ESMF_DELayout),  intent(in)              :: delayout
     integer,              intent(in)              :: de
     integer,              intent(out),  optional  :: rc
DESCRIPTION:

The PET who's service offer was accepted for de must use ESMF_DELayoutServiceComplete to close the service window.

The arguments are:

delayout
Specified ESMF_DELayout object.
de
DE for which to close service window.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

41.6.8 ESMF_DELayoutServiceOffer - Offer service for a DE in DELayout


INTERFACE:

   recursive function ESMF_DELayoutServiceOffer(delayout, de, rc)
ARGUMENTS:
     type(ESMF_DELayout),  intent(in)              :: delayout
     integer,              intent(in)              :: de
     integer,              intent(out),  optional  :: rc
RETURN VALUE:
     type(ESMF_DELayoutServiceReply) :: ESMF_DELayoutServiceOffer
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_DELAYOUT_SERVICE_ACCEPT if the service offer has been accepted by DELayout or ESMF_DELAYOUT_SERVICE_DENY if the service offer was denied. The service offer paradigm is different from a simple mutex approach in that 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.

The arguments are:

delayout
Specified ESMF_DELayout object.
de
DE for which service is offered by the calling PET.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

41.6.9 ESMF_DELayoutValidate - Validate DELayout internals


INTERFACE:

   subroutine ESMF_DELayoutValidate(delayout, rc)
ARGUMENTS:
     type(ESMF_DELayout),  intent(in)              :: delayout
     integer,              intent(out),  optional  :: rc
DESCRIPTION:

Validates that the delayout is internally consistent. The method returns an error code if problems are found.

The arguments are:

delayout
Specified ESMF_DELayout object.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

42 VM Class

42.1 Description

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 12.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, on the other hand, 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.

42.2 Use and Examples

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.

42.2.1 Global VM

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

  use ESMF_Mod
  
  implicit none
  
  ! local variables
  integer:: rc
  type(ESMF_VM):: vm
  integer:: localPet, petCount, peCount, ssiId, vas

  call ESMF_Initialize(vm=vm, 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_VMGetPETLocalInfo(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."

  call ESMF_Finalize(rc=rc)

end program

42.2.2 Getting the MPI Communicator from an VM object

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)

42.2.3 Nesting ESMF inside a user MPI application

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(rc=rc)
  ! ESMF_Initialize() does not call MPI_Init() if it finds MPI initialized.

  call ESMF_Finalize(terminationflag=ESMF_KEEPMPI, rc=rc)
  ! Calling with terminationflag=ESMF_KEEPMPI instructs ESMF_Finalize() to keep
  ! MPI active.

  call MPI_Finalize(ierr)
  ! It is the responsibility of the outer user code to finalize MPI.

42.2.4 Nesting ESMF inside a user MPI application on a subset of MPI ranks

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, rc=rc)
    ! Only call ESMF_Initialize() on rank 0 and 1, passing the prepared MPI
    ! communicator that spans these ranks.

    call ESMF_Finalize(terminationflag=ESMF_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.

42.2.5 Send/Recv

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, dst=dst, rc=rc)

  if (localPet==dst) &
    call ESMF_VMRecv(vm, recvData=localData, count=count, src=src, rc=rc)

42.2.6 Scatter and Gather

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, &
    root=scatterRoot, rc=rc)
  ! Both sendData and recvData must be 1-d arrays.

  call ESMF_VMGather(vm, sendData=array2, recvData=array1, count=nsize, &
    root=gatherRoot, rc=rc)
  ! Both sendData and recvData must be 1-d arrays.

42.2.7 AllReduce and AllFullReduce

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_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_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.

42.2.8 VM and Components

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 = 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 = 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 = 0
  end subroutine !--------------------------------------------------------------

end module

program ESMF_VMComponentEx
  use ESMF_Mod
  use ESMF_VMComponentEx_gcomp_mod
  implicit none
  
  ! local variables

  gcomp = ESMF_GridCompCreate(petList=(/0/), rc=rc)

  call ESMF_GridCompSetServices(gcomp, mygcomp_register, 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

42.3 Restrictions and Future Work

  1. Non-blocking Reduce() operations not implemented. None of the reduce communication calls have an implementation for the non-blocking feature. This affects:

  2. Limitations when using mpiuni mode. In mpiuni mode non-blocking communications are limited to one outstanding message per source-destination PET pair. Furthermore, in mpiuni mode the message length must be smaller than the internal ESMF buffer size.

  3. Alternative communication paths not accessible. All user accessible VM communication calls are currently implemented using MPI-1.2. VM's implementation of alternative communication techniques, such as shared memory between threaded PETs and POSIX IPC between PETs located on the same single system image, are currently inaccessible to the user. (One exception to this is the mpiuni case for which the VM automatically utilizes a shared memory path.)

  4. Data arrays in VM comm calls are assumed shape with rank=1. Currently all dummy arrays in VM comm calls are defined as assumed shape arrays of rank=1. The motivation for this choice is that the use of assumed shape dummy arrays guards against the Fortran copy in/out problem. However it may not be as flexible as desired from the user perspective. Alternatively all dummy arrays could be defined as assumed size arrays, as it is done in most MPI implementations, allowing arrays of various rank to be passed into the comm methods.

42.4 Design and Implementation Notes

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.

  1. Encapsulation of hardware and operating system details within the concept of Persistent Execution Threads (PETs).

  2. Resource management in terms of PETs with a guard against over-subscription.

  3. Topological description of the underlying configuration of the compute resources in terms of PETs.

  4. Transparent communication API for point-to-point and collective PET-based primitives, hiding the many different communication channels and offering best possible performance.

\scalebox{0.6}{\includegraphics{VM_design}}

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.

42.5 Class API

42.5.1 ESMF_VMAllFullReduce - Fully reduce data across VM, result on all PETs


INTERFACE:

    ! Private name; call using ESMF_VMAllFullReduce()
    subroutine ESMF_VMAllFullReduce<type><kind>(vm, sendData, recvData, count, &
      reduceflag,  blockingflag, 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_ReduceFlag),    intent(in)              :: reduceflag
      type(ESMF_BlockingFlag),  intent(in),   optional  :: blockingflag
      type(ESMF_CommHandle),    intent(out),  optional  :: commhandle
      integer,                  intent(out),  optional  :: rc
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 blockingflag = ESMF_NONBLOCKING error code ESMF_RC_NOT_IMPL will be returned and an error will be logged.

The arguments are:

vm
ESMF_VM object.
sendData
Contiguous data array holding data to be send. All PETs must specify a valid source array.
recvData
Single data variable to be received. All PETs must specify a valid result variable.
count
Number of elements in sendData. Must be the same on all PETs.
reduceflag
Reduction operation. See section 9.2.11 for a list of valid reduce operations.
[blockingflag]
Flag indicating whether this call behaves blocking or non-blocking:
ESMF_BLOCKING
(default) Block until local operation has completed.
ESMF_NONBLOCKING
Return immediately without blocking.
[commhandle]
If present, a communication handle will be returned in case of a non-blocking request (see argument blockingflag). The commhandle can be used in ESMF_VMCommWait() to block the calling PET until the communication call has finished PET-locally. If no commhandle was supplied to a non-blocking call the VM method ESMF_VMCommQueueWait() may be used to block on all currently queued communication calls of the VM context.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

42.5.2 ESMF_VMAllGather - Gather data across VM, result on all PETs


INTERFACE:

    ! Private name; call using ESMF_VMAllGather()
    subroutine ESMF_VMAllGather<type><kind>(vm, sendData, recvData, count, &
      blockingflag, 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_BlockingFlag),  intent(in),   optional  :: blockingflag
      type(ESMF_CommHandle),    intent(out),  optional  :: commhandle
      integer,                  intent(out),  optional  :: rc
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:

vm
ESMF_VM object.
sendData
Contiguous data array holding data to be send. All PETs must specify a valid source array.
recvData
Contiguous data array for data to be received. All PETs must specify a valid recvData argument.
count
Number of elements to be gathered from each PET. Must be the same on all PETs.
[blockingflag]
Flag indicating whether this call behaves blocking or non-blocking:
ESMF_BLOCKING
(default) Block until local operation has completed.
ESMF_NONBLOCKING
Return immediately without blocking.
[commhandle]
If present, a communication handle will be returned in case of a non-blocking request (see argument blockingflag). The commhandle can be used in ESMF_VMCommWait() to block the calling PET until the communication call has finished PET-locally. If no commhandle was supplied to a non-blocking call the VM method ESMF_VMCommQueueWait() may be used to block on all currently queued communication calls of the VM context.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

42.5.3 ESMF_VMAllGatherV - GatherV data across VM, result on all PETs


INTERFACE:

    ! Private name; call using ESMF_VMAllGatherV()
    subroutine ESMF_VMAllGatherV<type><kind>(vm, sendData, sendCount, recvData, &
      recvCounts, recvOffsets, blockingflag, 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(:)
      type(ESMF_BlockingFlag),  intent(in),   optional  :: blockingflag
      type(ESMF_CommHandle),    intent(out),  optional  :: commhandle
      integer,                  intent(out),  optional  :: rc
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 blockingflag = ESMF_NONBLOCKING error code ESMF_RC_NOT_IMPL will be returned and an error will be logged.

The arguments are:

vm
ESMF_VM object.
sendData
Contiguous data array holding data to be send. All PETs must specify a valid source array.
sendCount
Number of sendData elements to send from local PET to all other PETs.
recvData
Single data variable to be received. All PETs must specify a valid result variable.
recvCounts
Number of recvData elements to be received from corresponding source PET.
recvOffsets
Offsets in units of elements in recvData marking the start of element sequence to be received from source PET.
[blockingflag]
Flag indicating whether this call behaves blocking or non-blocking:
ESMF_BLOCKING
(default) Block until local operation has completed.
ESMF_NONBLOCKING
Return immediately without blocking.
[commhandle]
If present, a communication handle will be returned in case of a non-blocking request (see argument blockingflag). The commhandle can be used in ESMF_VMCommWait() to block the calling PET until the communication call has finished PET-locally. If no commhandle was supplied to a non-blocking call the VM method ESMF_VMCommQueueWait() may be used to block on all currently queued communication calls of the VM context.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

42.5.4 ESMF_VMAllReduce - Reduce data across VM, result on all PETs


INTERFACE:

    ! Private name; call using ESMF_VMAllReduce()
    subroutine ESMF_VMAllReduce<type><kind>(vm, sendData, recvData, count, &
      reduceflag, blockingflag, 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_ReduceFlag),    intent(in)              :: reduceflag
      type(ESMF_BlockingFlag),  intent(in),   optional  :: blockingflag
      type(ESMF_CommHandle),    intent(out),  optional  :: commhandle
      integer,                  intent(out),  optional  :: rc
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 blockingflag = ESMF_NONBLOCKING error code ESMF_RC_NOT_IMPL will be returned and an error will be logged.

The arguments are:

vm
ESMF_VM object.
sendData
Contiguous data array holding data to be send. All PETs must specify a valid source array.
recvData
Single data variable to be received. All PETs must specify a valid result variable.
count
Number of elements in sendData and recvData. Must be the same on all PETs.
reduceflag
Reduction operation. See section 9.2.11 for a list of valid reduce operations.
[blockingflag]
Flag indicating whether this call behaves blocking or non-blocking:
ESMF_BLOCKING
(default) Block until local operation has completed.
ESMF_NONBLOCKING
Return immediately without blocking.
[commhandle]
If present, a communication handle will be returned in case of a non-blocking request (see argument blockingflag). The commhandle can be used in ESMF_VMCommWait() to block the calling PET until the communication call has finished PET-locally. If no commhandle was supplied to a non-blocking call the VM method ESMF_VMCommQueueWait() may be used to block on all currently queued communication calls of the VM context.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

42.5.5 ESMF_VMAllToAllV - AllToAllV communications across VM


INTERFACE:

    ! Private name; call using ESMF_VMAllToAllV()
    subroutine ESMF_VMAllToAllV<type><kind>(vm, sendData, sendCounts, sendOffsets, &
      recvData, recvCounts, recvOffsets, blockingflag, 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(:)
      type(ESMF_BlockingFlag),  intent(in),   optional  :: blockingflag
      type(ESMF_CommHandle),    intent(out),  optional  :: commhandle
      integer,                  intent(out),  optional  :: rc
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 blockingflag = ESMF_NONBLOCKING error code ESMF_RC_NOT_IMPL will be returned and an error will be logged.

The arguments are:

vm
ESMF_VM object.
sendData
Contiguous data array holding data to be send. All PETs must specify a valid source array.
sendCounts
Number of sendData elements to send from local PET to destination PET.
sendOffsets
Offsets in units of elements in sendData marking to start of element sequence to be send from local PET to destination PET.
recvData
Single data variable to be received. All PETs must specify a valid result variable.
recvCounts
Number of recvData elements to be received by local PET from source PET.
recvOffsets
Offsets in units of elements in recvData marking to start of element sequence to be received by local PET from source PET.
[blockingflag]
Flag indicating whether this call behaves blocking or non-blocking:
ESMF_BLOCKING
(default) Block until local operation has completed.
ESMF_NONBLOCKING
Return immediately without blocking.
[commhandle]
If present, a communication handle will be returned in case of a non-blocking request (see argument blockingflag). The commhandle can be used in ESMF_VMCommWait() to block the calling PET until the communication call has finished PET-locally. If no commhandle was supplied to a non-blocking call the VM method ESMF_VMCommQueueWait() may be used to block on all currently queued communication calls of the VM context.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

42.5.6 ESMF_VMBarrier - VM wide barrier


INTERFACE:

   subroutine ESMF_VMBarrier(vm, rc)
ARGUMENTS:
     type(ESMF_VM),  intent(in)              :: vm
     integer,        intent(out),  optional  :: rc
DESCRIPTION:

Collective ESMF_VM communication call that blocks calling PET until all PETs of the VM context have issued the call.

The arguments are:

vm
ESMF_VM object.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

42.5.7 ESMF_VMBroadcast - Broadcast data across VM


INTERFACE:

    ! Private name; call using ESMF_VMBroadcast()
    subroutine ESMF_VMBroadcast<type><kind>(vm, bcstData, count, root, &
      blockingflag, commhandle, rc)
ARGUMENTS:
      type(ESMF_VM),            intent(in)              :: vm
      <type>(ESMF_KIND_<kind>), target,   intent(inout) :: bcstData(:)
      integer,                  intent(in)              :: count
      integer,                  intent(in)              :: root
      type(ESMF_BlockingFlag),  intent(in),   optional  :: blockingflag
      type(ESMF_CommHandle),    intent(out),  optional  :: commhandle
      integer,                  intent(out),  optional  :: rc
DESCRIPTION:

Collective ESMF_VM communication call that broadcasts a contiguous data array from PET root 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:

vm
ESMF_VM object.
bcstData
Contiguous data array. On root PET bcstData holds data that is to be broadcasted to all other PETs. On all other PETs bcstData is used to receive the broadcasted data.
count
Number of elements in sendData and recvData. Must be the same on all PETs.
root
Id of the root PET within the ESMF_VM object.
[blockingflag]
Flag indicating whether this call behaves blocking or non-blocking:
ESMF_BLOCKING
(default) Block until local operation has completed.
ESMF_NONBLOCKING
Return immediately without blocking.
[commhandle]
If present, a communication handle will be returned in case of a non-blocking request (see argument blockingflag). The commhandle can be used in ESMF_VMCommWait() to block the calling PET until the communication call has finished PET-locally. If no commhandle was supplied to a non-blocking call the VM method ESMF_VMCommQueueWait() may be used to block on all currently queued communication calls of the VM context.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

42.5.8 ESMF_VMGather - Gather data from across VM


INTERFACE:

    ! Private name; call using ESMF_VMGather()
    subroutine ESMF_VMGather<type><kind>(vm, sendData, recvData, count, root, &
      blockingflag, 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)              :: root
      type(ESMF_BlockingFlag),  intent(in),   optional  :: blockingflag
      type(ESMF_CommHandle),    intent(out),  optional  :: commhandle
      integer,                  intent(out),  optional  :: rc
DESCRIPTION:

Collective ESMF_VM communication call that gathers contiguous data from all PETs of an ESMF_VM object (including root) into an array on the root PET.

This method is overloaded for: ESMF_TYPEKIND_I4, ESMF_TYPEKIND_R4, ESMF_TYPEKIND_R8, ESMF_TYPEKIND_LOGICAL.

The arguments are:

vm
ESMF_VM object.
sendData
Contiguous data array holding data to be send. All PETs must specify a valid source array.
recvData
Contiguous data array for data to be received. Only the recvData array specified by the root PET will be used by this method.
count
Number of elements to be send from each PET to root. Must be the same on all PETs.
root
Id of the root PET within the ESMF_VM object.
[blockingflag]
Flag indicating whether this call behaves blocking or non-blocking:
ESMF_BLOCKING
(default) Block until local operation has completed.
ESMF_NONBLOCKING
Return immediately without blocking.
[commhandle]
If present, a communication handle will be returned in case of a non-blocking request (see argument blockingflag). The commhandle can be used in ESMF_VMCommWait() to block the calling PET until the communication call has finished PET-locally. If no commhandle was supplied to a non-blocking call the VM method ESMF_VMCommQueueWait() may be used to block on all currently queued communication calls of the VM context.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

42.5.9 ESMF_VMGatherV - GatherV data from across VM


INTERFACE:

    ! Private name; call using ESMF_VMGatherV()
    subroutine ESMF_VMGatherV<type><kind>(vm, sendData, sendCount, recvData, &
      recvCounts, recvOffsets, root, 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)              :: root
      integer,                  intent(out),  optional  :: rc
DESCRIPTION:

Collective ESMF_VM communication call that gathers contiguous data from all PETs of an ESMF_VM object into an array on root PET.

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 blockingflag = ESMF_NONBLOCKING error code ESMF_RC_NOT_IMPL will be returned and an error will be logged.

The arguments are:

vm
ESMF_VM object.
sendData
Contiguous data array holding data to be send. All PETs must specify a valid source array.
sendCount
Number of sendData elements to send from local PET to all other PETs.
recvData
Single data variable to be received. All PETs must specify a valid result variable.
recvCounts
Number of recvData elements to be received from corresponding source PET.
recvOffsets
Offsets in units of elements in recvData marking the start of element sequence to be received from source PET.
root
Id of the root PET within the ESMF_VM object.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

42.5.10 ESMF_VMGet - Get VM internals


INTERFACE:

   subroutine ESMF_VMGet(vm, localPet, petCount, peCount, mpiCommunicator, &
     pthreadsEnabledFlag, openMPEnabledFlag, rc)
ARGUMENTS:
     type(ESMF_VM),      intent(in)              :: vm
     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  :: rc
DESCRIPTION:

Get internal information about the specified ESMF_VM object.

The arguments are:

vm
Queried ESMF_VM object.
[localPet]
Upon return this holds the id of the PET that issued this call.
[petCount]
Upon return this holds the number of PETs in the specified ESMF_VM object.
[peCount]
Upon return this holds the number of PEs referenced by the specified ESMF_VM object.
[mpiCommunicator]
Upon return this holds the MPI intra-communicator used by the specified ESMF_VM object. This communicator may be used for user-level MPI communications. It is recommended that the user duplicates the communicator via MPI_Comm_Dup() in order to prevent any interference with ESMF communications.
[pthreadsEnabledFlag]
.TRUE.
ESMF has been compiled with Pthreads.
.FALSE.
ESMF has not been compiled with Pthreads.
[openMPEnabledFlag]
.TRUE.
ESMF has been compiled with OpenMP.
.FALSE.
ESMF has not been compiled with OpenMP.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

42.5.11 ESMF_VMGetGlobal - Get Global VM


INTERFACE:

   subroutine ESMF_VMGetGlobal(vm, rc)
ARGUMENTS:
     type(ESMF_VM), intent(out)            :: vm
     integer,       intent(out), optional  :: rc
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:

vm
Upon return this holds the ESMF_VM object of the global execution context.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

42.5.12 ESMF_VMGetCurrent - Get Current VM


INTERFACE:

   subroutine ESMF_VMGetCurrent(vm, rc)
ARGUMENTS:
     type(ESMF_VM), intent(out)            :: vm
     integer,       intent(out), optional  :: rc
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:

vm
Upon return this holds the ESMF_VM object of the current execution context.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

42.5.13 ESMF_VMGetPETLocalInfo - Get VM PET local internals


INTERFACE:

   subroutine ESMF_VMGetPETLocalInfo(vm, pet, peCount, ssiId, threadCount, &
     threadId, vas, rc)
ARGUMENTS:
     type(ESMF_VM),  intent(in)              :: vm
     integer,        intent(in)              :: pet
     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  :: rc
DESCRIPTION:

Get internal information about a specific PET within an ESMF_VM object.

The arguments are:

vm
Queried ESMF_VM object.
pet
Queried PET id within the specified ESMF_VM object.
[peCount]
Upon return this holds the number of PEs associated with the specified PET in the ESMF_VM object.
[ssiId]
Upon return this holds the id of the single-system image (SSI) the specified PET is running on.
[threadCount]
Upon return this holds the number of PETs in the specified PET"s thread group.
[threadId]
Upon return this holds the thread id of the specified PET within the PET"s thread group.
[vas]
Virtual address space in which this PET operates.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

42.5.14 ESMF_VMPrint - Print VM internals


INTERFACE:

   subroutine ESMF_VMPrint(vm, rc)
ARGUMENTS:
     type(ESMF_VM),  intent(in)              :: vm
     integer,        intent(out),  optional  :: rc
DESCRIPTION:

Print internal information about the specified ESMF_VM to stdout.

Note: Many ESMF_<class>Print methods are implemented in C++. On some platforms/compilers there is a potential issue with interleaving Fortran and C++ output to stdout such that it doesn't appear in the expected order. If this occurs, the ESMF_IOUnitFlush() method may be used on unit 6 to get coherent output.

The arguments are:

vm
Specified ESMF_VM object.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

42.5.15 ESMF_VMRecv - Receive data from src PET


INTERFACE:

    ! Private name; call using ESMF_VMRecv()
    subroutine ESMF_VMRecv<type><kind>(vm, recvData, count, src, blockingflag, &
      commhandle, rc)
ARGUMENTS:
      type(ESMF_VM),            intent(in)              :: vm
      integer(ESMF_KIND_I4), target,   intent(out)      :: recvData(:)  
      integer,                  intent(in)              :: count
      integer,                  intent(in)              :: src
      type(ESMF_BlockingFlag),  intent(in),   optional  :: blockingflag
      type(ESMF_CommHandle),    intent(out),  optional  :: commhandle
      integer,                  intent(out),  optional  :: rc
DESCRIPTION:

Receive contiguous data from src PET 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:

vm
ESMF_VM object.
recvData
Contiguous data array for data to be received.
count
Number of elements to be received.
src
Id of the source PET within the ESMF_VM object.
[blockingflag]
Flag indicating whether this call behaves blocking or non-blocking:
ESMF_BLOCKING
(default) Block until local operation has completed.
ESMF_NONBLOCKING
Return immediately without blocking.
[commhandle]
If present, a communication handle will be returned in case of a non-blocking request (see argument blockingflag). The commhandle can be used in ESMF_VMCommWait() to block the calling PET until the communication call has finished PET-locally. If no commhandle was supplied to a non-blocking call the VM method ESMF_VMCommQueueWait() may be used to block on all currently queued communication calls of the VM context.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

42.5.16 ESMF_VMReduce - Reduce data from across VM


INTERFACE:

    ! Private name; call using ESMF_VMReduce()
    subroutine ESMF_VMReduce<type><kind>(vm, sendData, recvData, count, &
      reduceflag, root, blockingflag, 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_ReduceFlag),    intent(in)              :: reduceflag
      integer,                  intent(in)              :: root
      type(ESMF_BlockingFlag),  intent(in),   optional  :: blockingflag
      type(ESMF_CommHandle),    intent(out),  optional  :: commhandle
      integer,                  intent(out),  optional  :: rc
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 root PET. 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 blockingflag = ESMF_NONBLOCKING error code ESMF_RC_NOT_IMPL will be returned and an error will be logged.

The arguments are:

vm
ESMF_VM object.
sendData
Contiguous data array holding data to be send. All PETs must specify a valid source array.
recvData
Single data variable to be received. All PETs must specify a valid result variable.
count
Number of elements in sendData and recvData. Must be the same on all PETs.
reduceflag
Reduction operation. See section 9.2.11 for a list of valid reduce operations.
root
Id of the root PET within the ESMF_VM object.
[blockingflag]
Flag indicating whether this call behaves blocking or non-blocking:
ESMF_BLOCKING
(default) Block until local operation has completed.
ESMF_NONBLOCKING
Return immediately without blocking.
[commhandle]
If present, a communication handle will be returned in case of a non-blocking request (see argument blockingflag). The commhandle can be used in ESMF_VMCommWait() to block the calling PET until the communication call has finished PET-locally. If no commhandle was supplied to a non-blocking call the VM method ESMF_VMCommQueueWait() may be used to block on all currently queued communication calls of the VM context.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

42.5.17 ESMF_VMScatter - Scatter data across VM


INTERFACE:

    ! Private name; call using ESMF_VMScatter()
    subroutine ESMF_VMScatter<type><kind>(vm, sendData, recvData, count, root, &
      blockingflag, 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)              :: root
      type(ESMF_BlockingFlag),  intent(in),   optional  :: blockingflag
      type(ESMF_CommHandle),    intent(out),  optional  :: commhandle
      integer,                  intent(out),  optional  :: rc
DESCRIPTION:

Collective ESMF_VM communication call that scatters contiguous data from the root PET to all PETs across the ESMF_VM object (including root).

This method is overloaded for: ESMF_TYPEKIND_I4, ESMF_TYPEKIND_R4, ESMF_TYPEKIND_R8, ESMF_TYPEKIND_LOGICAL.

The arguments are:

vm
ESMF_VM object.
sendData
Contiguous data array holding data to be send. Only the sendData array specified by the root PET will be used by this method.
recvData
Contiguous data array for data to be received. All PETs must specify a valid destination array.
count
Number of elements to be send from root to each of the PETs. Must be the same on all PETs.
root
Id of the root PET within the ESMF_VM object.
[blockingflag]
Flag indicating whether this call behaves blocking or non-blocking:
ESMF_BLOCKING
(default) Block until local operation has completed.
ESMF_NONBLOCKING
Return immediately without blocking.
[commhandle]
If present, a communication handle will be returned in case of a non-blocking request (see argument blockingflag). The commhandle can be used in ESMF_VMCommWait() to block the calling PET until the communication call has finished PET-locally. If no commhandle was supplied to a non-blocking call the VM method ESMF_VMCommQueueWait() may be used to block on all currently queued communication calls of the VM context.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

42.5.18 ESMF_VMScatterV - ScatterV across VM


INTERFACE:

    ! Private name; call using ESMF_VMScatterV()
    subroutine ESMF_VMScatterV<type><kind>(vm, sendData, sendCounts, sendOffsets, &
      recvData, recvCount, root, 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)              :: root
      integer,                  intent(out),  optional  :: rc
DESCRIPTION:

Collective ESMF_VM communication call that scatters contiguous data from the root PET to all PETs across the ESMF_VM object (including root).

This method is overloaded for: ESMF_TYPEKIND_I4, ESMF_TYPEKIND_R4, ESMF_TYPEKIND_R8.

The arguments are:

vm
ESMF_VM object.
sendData
Contiguous data array holding data to be send. Only the sendData array specified by the root PET will be used by this method.
sendCounts
Number of sendData elements to be send to corresponding receive PET.
sendOffsets
Offsets in units of elements in sendData marking the start of element sequence to be send to receive PET.
recvData
Single data variable to be received. All PETs must specify a valid result variable.
recvCount
Number of recvData elements to receive by local PET from root PET.
root
Id of the root PET within the ESMF_VM object.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

42.5.19 ESMF_VMSend - Send data to dst PET


INTERFACE:

    ! Private name; call using ESMF_VMSend()
    subroutine ESMF_VMSend<type><kind>(vm, sendData, count, dst, blockingflag, &
      commhandle, rc)
ARGUMENTS:
      type(ESMF_VM),            intent(in)              :: vm
      <type>(ESMF_KIND_<kind>), target,   intent(in)    :: sendData(:)  
      integer,                  intent(in)              :: count
      integer,                  intent(in)              :: dst
      type(ESMF_BlockingFlag),  intent(in),   optional  :: blockingflag
      type(ESMF_CommHandle),    intent(out),  optional  :: commhandle
      integer,                  intent(out),  optional  :: rc
DESCRIPTION:

Send contiguous data to dst PET within the same ESMF_VM object.

The arguments are:

vm
ESMF_VM object.
sendData
Contiguous data array holding data to be send.
count
Number of elements to be send.
dst
Id of the destination PET within the ESMF_VM object.
[blockingflag]
Flag indicating whether this call behaves blocking or non-blocking:
ESMF_BLOCKING
(default) Block until local operation has completed.
ESMF_NONBLOCKING
Return immediately without blocking.
[commhandle]
If present, a communication handle will be returned in case of a non-blocking request (see argument blockingflag). The commhandle can be used in ESMF_VMCommWait() to block the calling PET until the communication call has finished PET-locally. If no commhandle was supplied to a non-blocking call the VM method ESMF_VMCommQueueWait() may be used to block on all currently queued communication calls of the VM context.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

42.5.20 ESMF_VMSendRecv - Send and Recv data to and from PETs


INTERFACE:

    ! Private name; call using ESMF_VMSendRecv()
    subroutine ESMF_VMSendRecv<type><kind>(vm, sendData, sendCount, dst, &
      recvData, recvCount, src, blockingflag, commhandle, rc)
ARGUMENTS:
      type(ESMF_VM),            intent(in)              :: vm
      <type>(ESMF_KIND_<kind>), target,   intent(in)    :: sendData(:)  
      integer,                  intent(in)              :: sendCount
      integer,                  intent(in)              :: dst
      <type>(ESMF_KIND_<kind>), target,   intent(out)   :: recvData(:)  
      integer,                  intent(in)              :: recvCount
      integer,                  intent(in)              :: src
      type(ESMF_BlockingFlag),  intent(in),   optional  :: blockingflag
      type(ESMF_CommHandle),    intent(out),  optional  :: commhandle
      integer,                  intent(out),  optional  :: rc
DESCRIPTION:

Send contiguous data to dst PET within the same ESMF_VM object while receiving contiguous data from src PET 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:

vm
ESMF_VM object.
sendData
Contiguous data array holding data to be send.
sendCount
Number of elements to be send.
dst
Id of the destination PET within the ESMF_VM object.
recvData
Contiguous data array for data to be received.
recvCount
Number of elements to be received.
src
Id of the source PET within the ESMF_VM object.
[blockingflag]
Flag indicating whether this call behaves blocking or non-blocking:
ESMF_BLOCKING
(default) Block until local operation has completed.
ESMF_NONBLOCKING
Return immediately without blocking.
[commhandle]
If present, a communication handle will be returned in case of a non-blocking request (see argument blockingflag). The commhandle can be used in ESMF_VMCommWait() to block the calling PET until the communication call has finished PET-locally. If no commhandle was supplied to a non-blocking call the VM method ESMF_VMCommQueueWait() may be used to block on all currently queued communication calls of the VM context.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

42.5.21 ESMF_VMValidate - Validate VM internals


INTERFACE:

   subroutine ESMF_VMValidate(vm, rc)
ARGUMENTS:
     type(ESMF_VM),  intent(in)              :: vm
     integer,        intent(out),  optional  :: rc
DESCRIPTION:

Validates that the vm is internally consistent. The method returns an error code if problems are found.

The arguments are:

vm
Specified ESMF_VM object.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

42.5.22 ESMF_VMCommWait - Wait for non-blocking VM communication to complete


INTERFACE:

   subroutine ESMF_VMCommWait(vm, commhandle, rc)
ARGUMENTS:
     type(ESMF_VM),          intent(in)              :: vm
     type(ESMF_CommHandle),  intent(in)              :: commhandle
     integer,                intent(out),  optional  :: rc
DESCRIPTION:

Wait for non-blocking VM communication specified by the commhandle to complete.

The arguments are:

vm
ESMF_VM object.
commhandle
Handle specifying a previously issued non-blocking communication request.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

42.5.23 ESMF_VMCommQueueWait - Wait for all non-blocking VM comms to complete


INTERFACE:

   subroutine ESMF_VMCommQueueWait(vm, rc)
ARGUMENTS:
     type(ESMF_VM),          intent(in)              :: vm
     integer,                intent(out),  optional  :: rc
DESCRIPTION:

Wait for all pending non-blocking VM communication within the specified VM context to complete.

The arguments are:

vm
ESMF_VM object.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

42.5.24 ESMF_VMWtime - Get floating-point number of seconds


INTERFACE:

   subroutine ESMF_VMWtime(time, rc)
ARGUMENTS:
     real(ESMF_KIND_R8),     intent(out)             :: time
     integer,                intent(out),  optional  :: rc
DESCRIPTION:

Get floating-point number of seconds of elapsed wall-clock time since some time in the past.

The arguments are:

time
Time in seconds.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

42.5.25 ESMF_VMWtimeDelay - Delay execution


INTERFACE:

   subroutine ESMF_VMWtimeDelay(delay, rc)
ARGUMENTS:
     real(ESMF_KIND_R8),     intent(in)              :: delay
     integer,                intent(out),  optional  :: rc
DESCRIPTION:

Delay execution for amount of seconds.

The arguments are:

delay
Delay time in seconds.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

42.5.26 ESMF_VMWtimePrec - Timer precision as floating-point number of seconds


INTERFACE:

   subroutine ESMF_VMWtimePrec(prec, rc)
ARGUMENTS:
     real(ESMF_KIND_R8),     intent(out)             :: prec
     integer,                intent(out),  optional  :: rc
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:

prec
Timer precision in seconds.
[rc]
Return code; equals ESMF_SUCCESS if there are no errors.

43 Fortran I/O Utilities

43.1 Description

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.

43.2 Use and Examples


43.2.1 Fortran unit number management

The ESMF_IOUnitGet() method is provided so that applications using ESMF can remain free of unit number conflicts -- both when combined with other third party code, or with ESMF itself. This call is typically used just prior to an OPEN statement:

  call ESMF_IOUnitGet (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_IOUnitGet() 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.

43.2.2 Flushing output

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_IOUnitFlush() 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_IOUnitGet (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_IOUnitFlush (unit=tty_unit)
    end if
    call ESMF_VMBarrier (vm=vm)
  end do

43.3 Design and Implementation Notes

43.3.1 Fortran unit number management

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.

43.3.2 Flushing output

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.

43.4 Utility API

43.4.1 ESMF_IOUnitFlush - flush output on a unit number


INTERFACE:

   subroutine ESMF_IOUnitFlush (unit, rc)
PARAMETERS:
     integer, intent(in) :: unit
     integer, intent(out), optional :: rc
DESCRIPTION:

Call the system-dependent routine to force output on a specific Fortran unit number.

The arguments are:

[unit]
A Fortran I/O unit number.
[rc]
Return code; Returns either ESMF_SUCCESS or ESMF_FAILURE

43.4.2 ESMF_IOUnitGet - Scan for a free I/O unit number


INTERFACE:

   subroutine ESMF_IOUnitGet (unit, rc)
ARGUMENTS:
     integer, intent(out) :: unit
     integer, intent(out), optional :: rc
DESCRIPTION:

Scan for, and return, a free Fortran I/O unit number.

The arguments are:

[unit]
A Fortran I/O unit number.
[rc]
Return code; Returns either ESMF_SUCCESS or ESMF_FAILURE.

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.

44 References


next up previous contents
Next: Bibliography Up: ESMF_refdoc Previous: 3 Infrastructure: Fields and   Contents
esmf_support@list.woc.noaa.gov