ESMF_GridComp.F90 Source File


Source Code

! $Id$
!
! Earth System Modeling Framework
! Copyright (c) 2002-2023, University Corporation for Atmospheric Research,
! Massachusetts Institute of Technology, Geophysical Fluid Dynamics
! Laboratory, University of Michigan, National Centers for Environmental
! Prediction, Los Alamos National Laboratory, Argonne National Laboratory,
! NASA Goddard Space Flight Center.
! Licensed under the University of Illinois-NCSA License.
!
!==============================================================================
#define ESMF_FILENAME "ESMF_GridComp.F90"
!==============================================================================
!
! ESMF Gridded Component module
module ESMF_GridCompMod
!
!==============================================================================
!
! This file contains the Gridded Component class definition and all
!  Gridded Component class methods.
!
!------------------------------------------------------------------------------
! INCLUDES
#include "ESMF.h"

!------------------------------------------------------------------------------
!BOPI
! !MODULE: ESMF_GridCompMod - Gridded Component class.
!
! !DESCRIPTION:
!
! The code in this file implements the Fortran interfaces to the
! {\tt ESMF\_GridComp} class and associated functions and subroutines.
!
!
! !USES:
  use ESMF_UtilTypesMod
  use ESMF_LogErrMod
  use ESMF_BaseMod
  use ESMF_VMMod
  use ESMF_ConfigMod
  use ESMF_ClockTypeMod
  use ESMF_ClockMod
  use ESMF_StateTypesMod
  use ESMF_StateMod
  use ESMF_GridMod
  use ESMF_MeshMod
  use ESMF_LocStreamMod
  use ESMF_XGridMod
  use ESMF_CompMod
  use ESMF_InitMacrosMod
  use ESMF_IOUtilMod

  implicit none

!------------------------------------------------------------------------------
! !PRIVATE TYPES:
  private

!------------------------------------------------------------------------------
! !PUBLIC MEMBER FUNCTIONS:

! - ESMF-public methods:
  public operator(==)
  public operator(/=)

  public ESMF_GridCompCreate
  public ESMF_GridCompDestroy
  public ESMF_GridCompFinalize
  public ESMF_GridCompFinalizeAct
  public ESMF_GridCompGet
  public ESMF_GridCompGetEPPhaseCount
  public ESMF_GridCompInitialize
  public ESMF_GridCompInitializeAct
  public ESMF_GridCompIsCreated
  public ESMF_GridCompIsPetLocal
  public ESMF_GridCompPrint
  public ESMF_GridCompReadRestart
  public ESMF_GridCompRun
  public ESMF_GridCompRunAct
  public ESMF_GridCompServiceLoop
  public ESMF_GridCompSet
  public ESMF_GridCompSetEntryPoint
  public ESMF_GridCompSetServices
  public ESMF_GridCompSetVM
  public ESMF_GridCompSetVMMaxPEs
  public ESMF_GridCompSetVMMaxThreads
  public ESMF_GridCompSetVMMinThreads
  public ESMF_GridCompValidate
  public ESMF_GridCompWait
  public ESMF_GridCompWriteRestart

! - ESMF-internal methods:
  public ESMF_GridCompGetInit

!EOPI

!------------------------------------------------------------------------------
! The following line turns the CVS identifier string into a printable variable.
  character(*), parameter, private :: version = &
    '$Id$'

!==============================================================================
!
! INTERFACE BLOCKS
!
!==============================================================================

!------------------------------------------------------------------------------
  interface ESMF_GridCompSetServices
    module procedure ESMF_GridCompSetServices
    module procedure ESMF_GridCompSetServicesShObj
    module procedure ESMF_GridCompSetServicesComp
    module procedure ESMF_GridCompSetServicesSock
  end interface
!------------------------------------------------------------------------------

!------------------------------------------------------------------------------
  interface ESMF_GridCompSetVM
    module procedure ESMF_GridCompSetVM
    module procedure ESMF_GridCompSetVMShObj
  end interface
!------------------------------------------------------------------------------

!===============================================================================
! GridCompOperator() interfaces
!===============================================================================

! -------------------------- ESMF-public method -------------------------------
!BOP
! !IROUTINE: ESMF_GridCompAssignment(=) - GridComp assignment
!
! !INTERFACE:
!   interface assignment(=)
!   gridcomp1 = gridcomp2
!
! !ARGUMENTS:
!   type(ESMF_GridComp) :: gridcomp1
!   type(ESMF_GridComp) :: gridcomp2
!
! !STATUS:
! \begin{itemize}
! \item\apiStatusCompatibleVersion{5.2.0r}
! \end{itemize}
!
! !DESCRIPTION:
!   Assign gridcomp1 as an alias to the same ESMF GridComp object in memory
!   as gridcomp2. If gridcomp2 is invalid, then gridcomp1 will be equally invalid after
!   the assignment.
!
!   The arguments are:
!   \begin{description}
!   \item[gridcomp1]
!     The {\tt ESMF\_GridComp} object on the left hand side of the assignment.
!   \item[gridcomp2]
!     The {\tt ESMF\_GridComp} object on the right hand side of the assignment.
!   \end{description}
!
!EOP
!------------------------------------------------------------------------------


! -------------------------- ESMF-public method -------------------------------
!BOP
! !IROUTINE: ESMF_GridCompOperator(==) - GridComp equality operator
!
! !INTERFACE:
  interface operator(==)
!   if (gridcomp1 == gridcomp2) then ... endif
!             OR
!   result = (gridcomp1 == gridcomp2)
! !RETURN VALUE:
!   logical :: result
!
! !ARGUMENTS:
!   type(ESMF_GridComp), intent(in) :: gridcomp1
!   type(ESMF_GridComp), intent(in) :: gridcomp2
!
! !STATUS:
! \begin{itemize}
! \item\apiStatusCompatibleVersion{5.2.0r}
! \end{itemize}
!
! !DESCRIPTION:
!   Test whether gridcomp1 and gridcomp2 are valid aliases to the same ESMF
!   GridComp object in memory. For a more general comparison of two ESMF GridComps,
!   going beyond the simple alias test, the ESMF\_GridCompMatch() function (not yet
!   implemented) must be used.
!
!   The arguments are:
!   \begin{description}
!   \item[gridcomp1]
!     The {\tt ESMF\_GridComp} object on the left hand side of the equality
!     operation.
!   \item[gridcomp2]
!     The {\tt ESMF\_GridComp} object on the right hand side of the equality
!     operation.
!   \end{description}
!
!EOP
    module procedure ESMF_GridCompEQ

  end interface
!------------------------------------------------------------------------------


! -------------------------- ESMF-public method -------------------------------
!BOP
! !IROUTINE: ESMF_GridCompOperator(/=) - GridComp not equal operator
!
! !INTERFACE:
  interface operator(/=)
!   if (gridcomp1 /= gridcomp2) then ... endif
!             OR
!   result = (gridcomp1 /= gridcomp2)
! !RETURN VALUE:
!   logical :: result
!
! !ARGUMENTS:
!   type(ESMF_GridComp), intent(in) :: gridcomp1
!   type(ESMF_GridComp), intent(in) :: gridcomp2
!
! !STATUS:
! \begin{itemize}
! \item\apiStatusCompatibleVersion{5.2.0r}
! \end{itemize}
!
! !DESCRIPTION:
!   Test whether gridcomp1 and gridcomp2 are {\it not} valid aliases to the
!   same ESMF GridComp object in memory. For a more general comparison of two ESMF
!   GridComps, going beyond the simple alias test, the ESMF\_GridCompMatch() function
!   (not yet implemented) must be used.
!
!   The arguments are:
!   \begin{description}
!   \item[gridcomp1]
!     The {\tt ESMF\_GridComp} object on the left hand side of the non-equality
!     operation.
!   \item[gridcomp2]
!     The {\tt ESMF\_GridComp} object on the right hand side of the non-equality
!     operation.
!   \end{description}
!
!EOP
    module procedure ESMF_GridCompNE

  end interface
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------

!  integer, parameter :: ESMF_DEFAULT_TIMEOUT = 3600
  integer, parameter :: ESMF_DEFAULT_TIMEOUT = 300 ! Temporary

!------------------------------------------------------------------------------


!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

contains

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


!-------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompEQ()"
!BOPI
! !IROUTINE:  ESMF_GridCompEQ - Compare two GridComps for equality
!
! !INTERFACE:
  impure elemental function ESMF_GridCompEQ(gridcomp1, gridcomp2)
!
! !RETURN VALUE:
    logical :: ESMF_GridCompEQ

! !ARGUMENTS:
    type(ESMF_GridComp), intent(in) :: gridcomp1
    type(ESMF_GridComp), intent(in) :: gridcomp2

!
! !DESCRIPTION:
!   Test if both {\tt gridcomp1} and {\tt gridcomp2} alias the same ESMF GridComp
!   object.
!
!EOPI
!-------------------------------------------------------------------------------

    ESMF_INIT_TYPE gcinit1, gcinit2
    integer :: localrc1, localrc2
    logical :: lval1, lval2

    ! Use the following logic, rather than "ESMF-INIT-CHECK-DEEP", to gain
    ! init checks on both args, and in the case where both are uninitialized,
    ! to distinguish equality based on uninitialized type (uncreated,
    ! deleted).

    ! TODO: Consider moving this logic to C++: use Base class? status?
    !       Or replicate logic for C interface also.

    ! check inputs
    gcinit1 = ESMF_GridCompGetInit(gridcomp1)
    gcinit2 = ESMF_GridCompGetInit(gridcomp2)

    ! TODO: this line must remain split in two for SunOS f90 8.3 127000-03
    if (gcinit1 .eq. ESMF_INIT_CREATED .and. &
      gcinit2 .eq. ESMF_INIT_CREATED) then
      ESMF_GridCompEQ = associated(gridcomp1%compp,gridcomp2%compp)
    else
      ESMF_GridCompEQ = ESMF_FALSE
    endif

  end function ESMF_GridCompEQ
!-------------------------------------------------------------------------------


!-------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompNE()"
!BOPI
! !IROUTINE:  ESMF_GridCompNE - Compare two GridComps for non-equality
!
! !INTERFACE:
  impure elemental function ESMF_GridCompNE(gridcomp1, gridcomp2)
!
! !RETURN VALUE:
    logical :: ESMF_GridCompNE

! !ARGUMENTS:
    type(ESMF_GridComp), intent(in) :: gridcomp1
    type(ESMF_GridComp), intent(in) :: gridcomp2

!
! !DESCRIPTION:
!   Test if both {\tt gridcomp1} and {\tt gridcomp2} alias the same ESMF GridComp
!   object.
!
!EOPI
!-------------------------------------------------------------------------------

    ESMF_INIT_TYPE gcinit1, gcinit2
    integer :: localrc1, localrc2
    logical :: lval1, lval2

    ! Use the following logic, rather than "ESMF-INIT-CHECK-DEEP", to gain
    ! init checks on both args, and in the case where both are uninitialized,
    ! to distinguish equality based on uninitialized type (uncreated,
    ! deleted).

    ESMF_GridCompNE = .not.ESMF_GridCompEQ(gridcomp1, gridcomp2)

  end function ESMF_GridCompNE
!-------------------------------------------------------------------------------

!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompCreate"
!BOP
! !IROUTINE: ESMF_GridCompCreate - Create a GridComp
!
! !INTERFACE:
  recursive function ESMF_GridCompCreate(keywordEnforcer, grid, gridList, &
    mesh, meshList, locstream, locstreamList, xgrid, xgridList, &
    config, configFile, clock, petList, devList, contextflag, name, rc)
!
! !RETURN VALUE:
    type(ESMF_GridComp) :: ESMF_GridCompCreate
!
! !ARGUMENTS:
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    type(ESMF_Grid),         intent(in),    optional :: grid
    type(ESMF_Grid),         intent(in),    optional :: gridList(:)
    type(ESMF_Mesh),         intent(in),    optional :: mesh
    type(ESMF_Mesh),         intent(in),    optional :: meshList(:)
    type(ESMF_LocStream),    intent(in),    optional :: locstream
    type(ESMF_LocStream),    intent(in),    optional :: locstreamList(:)
    type(ESMF_XGrid),        intent(in),    optional :: xgrid
    type(ESMF_XGrid),        intent(in),    optional :: xgridList(:)
    type(ESMF_Config),       intent(in),    optional :: config
    character(len=*),        intent(in),    optional :: configFile
    type(ESMF_Clock),        intent(in),    optional :: clock
    integer,                 intent(in),    optional :: petList(:)
    integer,                 intent(in),    optional :: devList(:)
    type(ESMF_Context_Flag), intent(in),    optional :: contextflag
    character(len=*),        intent(in),    optional :: name
    integer,                 intent(out),   optional :: rc
!
! !STATUS:
! \begin{itemize}
! \item\apiStatusCompatibleVersion{5.2.0r}
! \item\apiStatusModifiedSinceVersion{5.2.0r}
! \begin{description}
! \begin{sloppypar}
! \item[7.1.0r] Added arguments {\tt gridList}, {\tt mesh}, {\tt meshList},
!   {\tt locstream}, {\tt locstreamList}, {\tt xgrid}, and {\tt xgridList}.
!   These arguments add support for holding references to multiple geom objects,
!   either of the same type, or different type, in the same
!   {\tt ESMF\_GridComp} object.
! \item[8.6.0] Added argument {\tt devList} to support management of accelerator
!   devices.
! \end{sloppypar}
! \end{description}
! \end{itemize}
!
! !DESCRIPTION:
! This interface creates an {\tt ESMF\_GridComp} object. By default, a
! separate VM context will be created for each component.  This implies
! creating a new MPI communicator and allocating additional memory to
! manage the VM resources. When running on a large number of processors,
! creating a separate VM for each component could be both time and memory
! inefficient.  If the application is sequential, i.e., each component is
! running on all the PETs of the global VM, it will be more efficient to use
! the global VM instead of creating a new one.  This can be done by setting
! {\tt contextflag} to ESMF\_CONTEXT\_PARENT\_VM.
!
! The return value is the new {\tt ESMF\_GridComp}.
!
! The arguments are:
! \begin{description}
! \item[{[grid]}]
!   Associate an {\tt ESMF\_Grid} object with the newly created component.
!   This is simply a convenience feature for the user. The ESMF library code
!   does not access the {\tt grid} object.
!   The {\tt grid} argument is mutually exclusive with the {\tt gridList}
!   argument. If both arguments are provided, the routine will fail, and an
!   error is returned in {\tt rc}.
!   By default, i.e. if neither {\tt grid} nor {\tt gridList} are provided,
!   no {\tt ESMF\_Grid} objects are associated with the component.
! \item[{[gridList]}]
!   Associate a list of {\tt ESMF\_Grid} objects with the newly created
!   component.
!   This is simply a convenience feature for the user. The ESMF library code
!   does not access the {\tt gridList} object.
!   The {\tt gridList} argument is mutually exclusive with the {\tt grid}
!   argument. If both arguments are provided, the routine will fail, and an
!   error is returned in {\tt rc}.
!   By default, i.e. if neither {\tt grid} nor {\tt gridList} are provided,
!   no {\tt ESMF\_Grid} objects are associated with the component.
! \item[{[mesh]}]
!   Associate an {\tt ESMF\_Mesh} object with the newly created component.
!   This is simply a convenience feature for the user. The ESMF library code
!   does not access the {\tt mesh} object.
!   The {\tt mesh} argument is mutually exclusive with the {\tt meshList}
!   argument. If both arguments are provided, the routine will fail, and an
!   error is returned in {\tt rc}.
!   By default, i.e. if neither {\tt mesh} nor {\tt meshList} are provided,
!   no {\tt ESMF\_Mesh} objects are associated with the component.
! \item[{[meshList]}]
!   Associate a list of {\tt ESMF\_Mesh} objects with the newly created
!   component.
!   This is simply a convenience feature for the user. The ESMF library code
!   does not access the {\tt meshList} object.
!   The {\tt meshList} argument is mutually exclusive with the {\tt mesh}
!   argument. If both arguments are provided, the routine will fail, and an
!   error is returned in {\tt rc}.
!   By default, i.e. if neither {\tt mesh} nor {\tt meshList} are provided,
!   no {\tt ESMF\_Mesh} objects are associated with the component.
! \item[{[locstream]}]
!   Associate an {\tt ESMF\_LocStream} object with the newly created component.
!   This is simply a convenience feature for the user. The ESMF library code
!   does not access the {\tt locstream} object.
!   The {\tt locstream} argument is mutually exclusive with the
!   {\tt locstreamList}
!   argument. If both arguments are provided, the routine will fail, and an
!   error is returned in {\tt rc}.
!   By default, i.e. if neither {\tt locstream} nor {\tt locstreamList} are
!   provided, no {\tt ESMF\_LocStream} objects are associated with the
!   component.
! \item[{[locstreamList]}]
!   Associate a list of {\tt ESMF\_LocStream} objects with the newly created
!   component.
!   This is simply a convenience feature for the user. The ESMF library code
!   does not access the {\tt locstreamList} object.
!   The {\tt locstreamList} argument is mutually exclusive with the
!   {\tt locstream}
!   argument. If both arguments are provided, the routine will fail, and an
!   error is returned in {\tt rc}.
!   By default, i.e. if neither {\tt locstream} nor {\tt locstreamList} are
!   provided, no {\tt ESMF\_LocStream} objects are associated with the
!   component.
! \item[{[xgrid]}]
!   Associate an {\tt ESMF\_XGrid} object with the newly created component.
!   This is simply a convenience feature for the user. The ESMF library code
!   does not access the {\tt xgrid} object.
!   The {\tt xgrid} argument is mutually exclusive with the {\tt xgridList}
!   argument. If both arguments are provided, the routine will fail, and an
!   error is returned in {\tt rc}.
!   By default, i.e. if neither {\tt xgrid} nor {\tt xgridList} are provided,
!   no {\tt ESMF\_XGrid} objects are associated with the component.
! \item[{[xgridList]}]
!   Associate a list of {\tt ESMF\_XGrid} objects with the newly created
!   component.
!   This is simply a convenience feature for the user. The ESMF library code
!   does not access the {\tt xgridList} object.
!   The {\tt xgridList} argument is mutually exclusive with the {\tt xgrid}
!   argument. If both arguments are provided, the routine will fail, and an
!   error is returned in {\tt rc}.
!   By default, i.e. if neither {\tt xgrid} nor {\tt xgridList} are provided,
!   no {\tt ESMF\_XGrid} objects are associated with the component.
! \item[{[config]}]
!   An already-created {\tt ESMF\_Config} object to be attached to the newly
!   created component.
!   If both {\tt config} and {\tt configFile} arguments are specified,
!   {\tt config} takes priority.
! \item[{[configFile]}]
!   The filename of an {\tt ESMF\_Config} format file.
!   If specified, a new {\tt ESMF\_Config} object is created and attached to the
!   newly created component. The {\tt configFile} file is opened and associated
!   with the new config object.
!   If both {\tt config} and {\tt configFile} arguments are specified,
!   {\tt config} takes priority.
! \item[{[clock]}]
!   \begin{sloppypar}
!   Component-specific {\tt ESMF\_Clock}.  This clock is available to be
!   queried and updated by the new {\tt ESMF\_GridComp} as it chooses.
!   This should
!   not be the parent component clock, which should be maintained and passed
!   down to the initialize/run/finalize routines separately.
!   \end{sloppypar}
! \item[{[petList]}]
!   List of parent {\tt PET}s given to the created child component by the
!   parent component. If {\tt petList} is not specified, or is empty, all of the
!   parent {\tt PET}s are given to the child component. The order of
!   PETs in {\tt petList} determines how the child local PETs map back to
!   the parent PETs.
! \item[{[devList]}]
!   List of accelerator devices global ids {\tt DEV}s to be associated with the
!   created child component. If {\tt devList} is not specified, or is empty,
!   no devices are associated with the component.
! \item[{[contextflag]}]
!   Specify the component's VM context. The default context is
!   {\tt ESMF\_CONTEXT\_OWN\_VM}. See section \ref{const:contextflag} for a
!   complete list of valid flags.
! \item[{[name]}]
!   Name of the newly-created {\tt ESMF\_GridComp}.  This name can be altered
!   from within the {\tt ESMF\_GridComp} code once the initialization routine
!   is called.
! \item[{[rc]}]
!   Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOP
!------------------------------------------------------------------------------
    type(ESMF_CompClass), pointer :: compclass       ! generic comp
    type(ESMF_GridComp)           :: gcomp
    integer :: localrc                               ! local error status

    ESMF_INIT_CHECK_DEEP(ESMF_GridGetInit,grid,rc)
    ESMF_INIT_CHECK_DEEP(ESMF_ConfigGetInit,config,rc)
    ESMF_INIT_CHECK_DEEP(ESMF_ClockGetInit,clock,rc)

    ! Initialize the pointer to null.
    nullify(ESMF_GridCompCreate%compp)
    nullify(compclass)

    ! initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ! Allocate a new comp class
    allocate(compclass, stat=localrc)
    if (ESMF_LogFoundAllocError(localrc, msg="compclass", &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! call Comp method
    call ESMF_CompConstruct(compclass, ESMF_COMPTYPE_GRID, name, &
      configFile=configFile, config=config, clock=clock, petList=petList, &
      devList=devList, contextflag=contextflag, rc=localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) then
      deallocate(compclass)
      return
    endif

    gcomp%compp => compclass
    ! Add reference to this object into ESMF garbage collection table
    call c_ESMC_VMAddFObject(gcomp, ESMF_ID_COMPONENT%objectID)

    ! Set return values
    ESMF_GridCompCreate%compp => compclass

    ESMF_INIT_SET_CREATED(ESMF_GridCompCreate)

    ! deal with geom object arguments
    call ESMF_GridCompSet(ESMF_GridCompCreate, grid=grid, gridList=gridList, &
      mesh=mesh, meshList=meshList, locstream=locstream, &
      locstreamList=locstreamList, xgrid=xgrid, xgridList=xgridList, rc=localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS

  end function ESMF_GridCompCreate
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompDestroy"
!BOP
! !IROUTINE: ESMF_GridCompDestroy - Release resources associated with a GridComp
!
! !INTERFACE:
  recursive subroutine ESMF_GridCompDestroy(gridcomp, keywordEnforcer, &
    timeout, timeoutFlag, rc)
!
! !ARGUMENTS:
    type(ESMF_GridComp), intent(inout)          :: gridcomp
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    integer,             intent(in),   optional :: timeout
    logical,             intent(out),  optional :: timeoutFlag
    integer,             intent(out),  optional :: rc
!
! !STATUS:
! \begin{itemize}
! \item\apiStatusCompatibleVersion{5.2.0r}
! \item\apiStatusModifiedSinceVersion{5.2.0r}
! \begin{description}
! \item[5.3.0] Added argument {\tt timeout}.
!              Added argument {\tt timeoutFlag}.
!              The new arguments provide access to the fault-tolerant component
!              features.
! \end{description}
! \end{itemize}
!
! !DESCRIPTION:
! Destroys an {\tt ESMF\_GridComp}, releasing the resources associated
! with the object.
!
! The arguments are:
! \begin{description}
! \item[gridcomp]
!   Release all resources associated with this {\tt ESMF\_GridComp}
!   and mark the object as invalid.  It is an error to pass this
!   object into any other routines after being destroyed.
! \item[{[timeout]}]
!   The maximum period in seconds that this call will wait in communications
!   with the actual component, before returning with a timeout condition.
!   The default is 3600, i.e. 1 hour. The {\tt timeout} argument is only
!   supported for connected dual components.
! \item[{[timeoutFlag]}]
!   Returns {\tt .true.} if the timeout was reached, {\tt .false.} otherwise.
!   If {\tt timeoutFlag} was {\em not} provided, a timeout condition will lead
!   to a return code of {\tt rc \textbackslash = ESMF\_SUCCESS}. Otherwise the
!   return value of {\tt timeoutFlag} is the sole indicator of a timeout
!   condition.
! \item[{[rc]}]
!   Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOP
!------------------------------------------------------------------------------
    integer :: localrc                       ! local error status

    ! initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit,gridcomp,rc)

    ! Check to see if already destroyed
    if (.not.associated(gridcomp%compp)) then
      if (ESMF_LogFoundError(ESMF_RC_OBJ_BAD, &
        msg="GridComp not initialized or already destroyed", &
        ESMF_CONTEXT, rcToReturn=rc)) return
    endif

    ! check consistency between timeout argument and component argument
    if (present(timeout).and. &
      .not.ESMF_CompIsDualConnected(gridcomp%compp, rc=localrc)) then
      call ESMF_LogSetError(ESMF_RC_ARG_INCOMP, &
        msg="'timeout' argument is only allowed for connected dual components",&
        ESMF_CONTEXT, rcToReturn=rc)
      return
    endif

    ! call Comp method
    call ESMF_CompDestruct(gridcomp%compp, timeout=timeout, &
      timeoutFlag=timeoutFlag, rc=localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! mark object invalid
    call ESMF_BaseSetStatus(gridcomp%compp%base, ESMF_STATUS_INVALID, &
      rc=localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ESMF_INIT_SET_DELETED(gridcomp)

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS

  end subroutine ESMF_GridCompDestroy
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompFinalize"
!BOP
! !IROUTINE: ESMF_GridCompFinalize - Call the GridComp's finalize routine
!
! !INTERFACE:
  recursive subroutine ESMF_GridCompFinalize(gridcomp, keywordEnforcer, &
    importState, exportState, clock, syncflag, phase, timeout, timeoutFlag, &
    userRc, rc)
!
! !ARGUMENTS:
    type(ESMF_GridComp),  intent(inout)           :: gridcomp
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    type(ESMF_State),     intent(inout), optional :: importState
    type(ESMF_State),     intent(inout), optional :: exportState
    type(ESMF_Clock),     intent(inout), optional :: clock
    type(ESMF_Sync_Flag), intent(in),    optional :: syncflag
    integer,              intent(in),    optional :: phase
    integer,              intent(in),    optional :: timeout
    logical,              intent(out),   optional :: timeoutFlag
    integer,              intent(out),   optional :: userRc
    integer,              intent(out),   optional :: rc
!
! !STATUS:
! \begin{itemize}
! \item\apiStatusCompatibleVersion{5.2.0r}
! \item\apiStatusModifiedSinceVersion{5.2.0r}
! \begin{description}
! \item[5.3.0] Added argument {\tt timeout}.
!              Added argument {\tt timeoutFlag}.
!              The new arguments provide access to the fault-tolerant component
!              features.
! \end{description}
! \end{itemize}
!
! !DESCRIPTION:
! Call the associated user-supplied finalization routine for
! an {\tt ESMF\_GridComp}.
!
! The arguments are:
! \begin{description}
! \item[gridcomp]
!   The {\tt ESMF\_GridComp} to call finalize routine for.
! \item[{[importState]}]
!   {\tt ESMF\_State} containing import data. If not present, a dummy
!   argument will be passed to the user-supplied routine.  The
!   importState argument in the user code cannot be optional.
! \item[{[exportState]}]
!   {\tt ESMF\_State} containing export data. If not present, a dummy
!   argument will be passed to the user-supplied routine.  The
!   exportState argument in the user code cannot be optional.
! \item[{[clock]}]
!   External {\tt ESMF\_Clock} for passing in time information.
!   This is generally the parent component's clock, and will be treated
!   as read-only by the child component.  The child component can maintain
!   a private clock for its own internal time computations. If not present, a dummy
!   argument will be passed to the user-supplied routine.  The
!   clock argument in the user code cannot be optional.
! \item[{[syncflag]}]
!   Blocking behavior of this method call. See section \ref{const:sync}
!   for a list of valid blocking options. Default option is
!   {\tt ESMF\_SYNC\_VASBLOCKING} which blocks PETs and their spawned off threads
!   across each VAS but does not synchronize PETs that run in different VASs.
! \item[{[phase]}]
!   Component providers must document whether each of their
!   routines are {\em single-phase} or {\em multi-phase}.
!   Single-phase routines require only one invocation to complete
!   their work.
!   Multi-phase routines provide multiple subroutines to accomplish
!   the work, accommodating components which must complete part of their
!   work, return to the caller and allow other processing to occur,
!   and then continue the original operation.
!   For multiple-phase child components, this is the integer phase
!   number to be invoked.
!   For single-phase child components this argument is optional. The default
!   is 1.
! \item[{[timeout]}]
!   The maximum period in seconds that this call will wait in communications
!   with the actual component, before returning with a timeout condition.
!   The default is 3600, i.e. 1 hour. The {\tt timeout} argument is only
!   supported for connected dual components.
! \item[{[timeoutFlag]}]
!   Returns {\tt .true.} if the timeout was reached, {\tt .false.} otherwise.
!   If {\tt timeoutFlag} was {\em not} provided, a timeout condition will lead
!   to a return code of {\tt rc \textbackslash = ESMF\_SUCCESS}. Otherwise the
!   return value of {\tt timeoutFlag} is the sole indicator of a timeout
!   condition.
! \item[{[userRc]}]
!   Return code set by {\tt userRoutine} before returning.
! \item[{[rc]}]
!   Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOP
!------------------------------------------------------------------------------
    integer :: localrc                        ! local return code
    integer :: timeoutArg

    ! initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit,gridcomp,rc)

    ! check consistency between timeout argument and component argument
    if (present(timeout).and. &
      .not.ESMF_CompIsDualConnected(gridcomp%compp, rc=localrc)) then
      call ESMF_LogSetError(ESMF_RC_ARG_INCOMP, &
        msg="'timeout' argument is only allowed for connected dual components",&
        ESMF_CONTEXT, rcToReturn=rc)
      return
    endif

    timeoutArg = ESMF_DEFAULT_TIMEOUT ! default 1h
    if (present(timeout)) timeoutArg = timeout

    ! call Comp method
    call ESMF_CompExecute(gridcomp%compp, method=ESMF_METHOD_FINALIZEIC, &
      importState=importState, exportState=exportState, clock=clock, &
      syncflag=syncflag, phase=phase, timeout=timeoutArg, &
      userRc=userRc, rc=localrc)
    ! conditionally filter out the RC_TIMEOUT and return success
    if (present(timeoutFlag)) then
      timeoutFlag = .false. ! initialize
      if ((localrc==ESMF_RC_TIMEOUT).or.(localrc==ESMC_RC_TIMEOUT)) then
        timeoutFlag = .true.      ! indicate timeout through flag argument
        localrc = ESMF_SUCCESS    ! do not raise error condition on user level
      endif
    endif
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS
  end subroutine ESMF_GridCompFinalize
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompFinalizeAct"
!BOPI
! !IROUTINE: ESMF_GridCompFinalizeAct - Call the GridComp's finalize routine
!
! !INTERFACE:
  recursive subroutine ESMF_GridCompFinalizeAct(gridcomp, importState, &
    exportState, clock, syncflag, phase, userRc, rc)
!
! !ARGUMENTS:
    type(ESMF_GridComp),  intent(inout)           :: gridcomp
    type(ESMF_State),     intent(inout), optional :: importState
    type(ESMF_State),     intent(inout), optional :: exportState
    type(ESMF_Clock),     intent(inout), optional :: clock
    type(ESMF_Sync_Flag), intent(in),    optional :: syncflag
    integer,              intent(in),    optional :: phase
    integer,              intent(out),   optional :: userRc
    integer,              intent(out),   optional :: rc
!
! !DESCRIPTION:
! Same as {\tt ESMF\_GridCompFinalize} but no redirection through the
! Interface Component method, instead directly call into the actual method.
!
!EOPI
!------------------------------------------------------------------------------
    integer :: localrc                        ! local return code

    ! initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit,gridcomp,rc)

    ! call Comp method
    call ESMF_CompExecute(gridcomp%compp, method=ESMF_METHOD_FINALIZE, &
      importState=importState, exportState=exportState, clock=clock, &
      syncflag=syncflag, phase=phase, userRc=userRc, rc=localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS
  end subroutine ESMF_GridCompFinalizeAct
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompGet"
!BOP
! !IROUTINE: ESMF_GridCompGet - Get GridComp information
!
! !INTERFACE:
  recursive subroutine ESMF_GridCompGet(gridcomp, keywordEnforcer, &
    gridIsPresent, grid, gridList, meshIsPresent, mesh, meshList, &
    locstreamIsPresent, locstream, locstreamList, xgridIsPresent, &
    xgrid, xgridList, importStateIsPresent, importState, &
    exportStateIsPresent, exportState, configIsPresent, config, &
    configFileIsPresent, configFile, clockIsPresent, clock, localPet, &
    petCount, contextflag, currentMethod, currentPhase, comptype, &
    vmIsPresent, vm, name, rc)
!
! !ARGUMENTS:
    type(ESMF_GridComp),           intent(in)            :: gridcomp
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    logical,                       intent(out), optional :: gridIsPresent
    type(ESMF_Grid),               intent(out), optional :: grid
    type(ESMF_Grid), allocatable,  intent(out), optional :: gridList(:)
    logical,                       intent(out), optional :: meshIsPresent
    type(ESMF_Mesh),               intent(out), optional :: mesh
    type(ESMF_Mesh), allocatable,  intent(out), optional :: meshList(:)
    logical,                       intent(out), optional :: locstreamIsPresent
    type(ESMF_LocStream),          intent(out), optional :: locstream
    type(ESMF_LocStream), allocatable, intent(out), optional :: locstreamList(:)
    logical,                       intent(out), optional :: xgridIsPresent
    type(ESMF_XGrid),              intent(out), optional :: xgrid
    type(ESMF_XGrid), allocatable, intent(out), optional :: xgridList(:)
    logical,                       intent(out), optional :: importStateIsPresent
    type(ESMF_State),              intent(out), optional :: importState
    logical,                       intent(out), optional :: exportStateIsPresent
    type(ESMF_State),              intent(out), optional :: exportState
    logical,                       intent(out), optional :: configIsPresent
    type(ESMF_Config),             intent(out), optional :: config
    logical,                       intent(out), optional :: configFileIsPresent
    character(len=*),              intent(out), optional :: configFile
    logical,                       intent(out), optional :: clockIsPresent
    type(ESMF_Clock),              intent(out), optional :: clock
    integer,                       intent(out), optional :: localPet
    integer,                       intent(out), optional :: petCount
    type(ESMF_Context_Flag),       intent(out), optional :: contextflag
    type(ESMF_Method_Flag),        intent(out), optional :: currentMethod
    integer,                       intent(out), optional :: currentPhase
    type(ESMF_CompType_Flag),      intent(out), optional :: comptype
    logical,                       intent(out), optional :: vmIsPresent
    type(ESMF_VM),                 intent(out), optional :: vm
    character(len=*),              intent(out), optional :: name
    integer,                       intent(out), optional :: rc
!
! !STATUS:
! \begin{itemize}
! \item\apiStatusCompatibleVersion{5.2.0r}
! \item\apiStatusModifiedSinceVersion{5.2.0r}
! \begin{description}
! \begin{sloppypar}
! \item[7.1.0r] Added arguments {\tt gridList}, {\tt meshIsPresent}, {\tt mesh},
!   {\tt meshList}, {\tt locstreamIsPresent}, {\tt locstream},
!   {\tt locstreamList}, {\tt xgridIsPresent}, {\tt xgrid}, and {\tt xgridList}.
!   These arguments add support for accessing references to multiple geom objects,
!   either of the same type, or different type, associated with the same
!   {\tt ESMF\_GridComp} object.
! \end{sloppypar}
! \end{description}
! \end{itemize}
!
! !DESCRIPTION:
! Get information about an {\tt ESMF\_GridComp} object.
!
! The arguments are:
! \begin{description}
! \item[gridcomp]
!   The {\tt ESMF\_GridComp} object being queried.
! \item[{[gridIsPresent]}]
!   Set to {\tt .true.} if at least one {\tt ESMF\_Grid} object is
!   associated with the {\tt gridcomp} component.
!   Set to {\tt .false.} otherwise.
! \item[{[grid]}]
!   Return the {\tt ESMF\_Grid} object associated with the {\tt gridcomp}
!   component. If multiple {\tt ESMF\_Grid} objects are associated, return the
!   first in the list.
!   It is an error to query for {\tt grid} if no {\tt ESMF\_Grid} object is
!   associated with the {\tt gridcomp} component.
!   If unsure, query for {\tt gridIsPresent} first, or use the {\tt gridList}
!   variant.
! \item[{[gridList]}]
!   Return a list of all {\tt ESMF\_Grid} objects associated with the
!   {\tt gridcomp} component. The size of the returned {\tt gridList}
!   corresponds to the number of {\tt ESMF\_Grid} objects associated.
!   If no {\tt ESMF\_Grid} object is associated with the {\tt gridcomp}
!   component, the size of the returned {\tt gridList} is zero.
! \item[{[meshIsPresent]}]
!   Set to {\tt .true.} if at least one {\tt ESMF\_Mesh} object is
!   associated with the {\tt gridcomp} component.
!   Set to {\tt .false.} otherwise.
! \item[{[mesh]}]
!   Return the {\tt ESMF\_Mesh} object associated with the {\tt gridcomp}
!   component. If multiple {\tt ESMF\_Mesh} objects are associated, return the
!   first in the list.
!   It is an error to query for {\tt mesh} if no {\tt ESMF\_Mesh} object is
!   associated with the {\tt gridcomp} component.
!   If unsure, query for {\tt meshIsPresent} first, or use the {\tt meshList}
!   variant.
! \item[{[meshList]}]
!   Return a list of all {\tt ESMF\_Mesh} objects associated with the
!   {\tt gridcomp} component. The size of the returned {\tt meshList}
!   corresponds to the number of {\tt ESMF\_Mesh} objects associated.
!   If no {\tt ESMF\_Mesh} object is associated with the {\tt gridcomp}
!   component, the size of the returned {\tt meshList} is zero.
! \item[{[locstreamIsPresent]}]
!   Set to {\tt .true.} if at least one {\tt ESMF\_LocStream} object is
!   associated with the {\tt gridcomp} component.
!   Set to {\tt .false.} otherwise.
! \item[{[locstream]}]
! \begin{sloppypar}
!   Return the {\tt ESMF\_LocStream} object associated with the {\tt gridcomp}
!   component. If multiple {\tt ESMF\_LocStream} objects are associated, return
!   the first in the list.
!   It is an error to query for {\tt locstream} if no {\tt ESMF\_Grid} object is
!   associated with the {\tt gridcomp} component.
!   If unsure, query for {\tt locstreamIsPresent} first, or use the
!   {\tt locstreamList} variant.
! \end{sloppypar}
! \item[{[locstreamList]}]
!   Return a list of all {\tt ESMF\_LocStream} objects associated with the
!   {\tt gridcomp} component. The size of the returned {\tt locstreamList}
!   corresponds to the number of {\tt ESMF\_LocStream} objects associated.
!   If no {\tt ESMF\_LocStream} object is associated with the {\tt gridcomp}
!   component, the size of the returned {\tt locstreamList} is zero.
! \item[{[xgridIsPresent]}]
!   Set to {\tt .true.} if at least one {\tt ESMF\_XGrid} object is
!   associated with the {\tt gridcomp} component.
!   Set to {\tt .false.} otherwise.
! \item[{[xgrid]}]
!   Return the {\tt ESMF\_XGrid} object associated with the {\tt gridcomp}
!   component. If multiple {\tt ESMF\_XGrid} objects are associated, return the
!   first in the list.
!   It is an error to query for {\tt xgrid} if no {\tt ESMF\_XGrid} object is
!   associated with the {\tt gridcomp} component.
!   If unsure, query for {\tt xgridIsPresent} first, or use the {\tt xgridList}
!   variant.
! \item[{[xgridList]}]
!   Return a list of all {\tt ESMF\_XGrid} objects associated with the
!   {\tt gridcomp} component. The size of the returned {\tt xgridList}
!   corresponds to the number of {\tt ESMF\_XGrid} objects associated.
!   If no {\tt ESMF\_XGrid} object is associated with the {\tt gridcomp}
!   component, the size of the returned {\tt xgridList} is zero.
! \item[{[importStateIsPresent]}]
!   {\tt .true.} if {\tt importState} was set in GridComp object,
!   {\tt .false.} otherwise.
! \item[{[importState]}]
!   Return the associated import State.
!   It is an error to query for the import State if none is associated with
!   the GridComp. If unsure, get {\tt importStateIsPresent} first to determine
!   the status.
! \item[{[exportStateIsPresent]}]
!   {\tt .true.} if {\tt exportState} was set in GridComp object,
!   {\tt .false.} otherwise.
! \item[{[exportState]}]
!   Return the associated export State.
!   It is an error to query for the export State if none is associated with
!   the GridComp. If unsure, get {\tt exportStateIsPresent} first to determine
!   the status.
! \item[{[configIsPresent]}]
!   {\tt .true.} if {\tt config} was set in GridComp object,
!   {\tt .false.} otherwise.
! \item[{[config]}]
!   Return the associated Config.
!   It is an error to query for the Config if none is associated with
!   the GridComp. If unsure, get {\tt configIsPresent} first to determine
!   the status.
! \item[{[configFileIsPresent]}]
!   {\tt .true.} if {\tt configFile} was set in GridComp object,
!   {\tt .false.} otherwise.
! \item[{[configFile]}]
!   Return the associated configuration filename.
!   It is an error to query for the configuration filename if none is associated with
!   the GridComp. If unsure, get {\tt configFileIsPresent} first to determine
!   the status.
! \item[{[clockIsPresent]}]
!   {\tt .true.} if {\tt clock} was set in GridComp object,
!   {\tt .false.} otherwise.
! \item[{[clock]}]
!   Return the associated Clock.
!   It is an error to query for the Clock if none is associated with
!   the GridComp. If unsure, get {\tt clockIsPresent} first to determine
!   the status.
! \item[{[localPet]}]
!   Return the local PET id within the {\tt ESMF\_GridComp} object.
! \item[{[petCount]}]
!   Return the number of PETs in the the {\tt ESMF\_GridComp} object.
! \item[{[contextflag]}]
!   Return the {\tt ESMF\_Context\_Flag} for this {\tt ESMF\_GridComp}.
!   See section \ref{const:contextflag} for a complete list of valid flags.
! \item[{[currentMethod]}]
!   Return the current {\tt ESMF\_Method\_Flag} of the {\tt ESMF\_GridComp}
!   execution. See section \ref{const:method}  for a complete list of valid
!   options.
! \item[{[currentPhase]}]
!   Return the current {\tt phase} of the {\tt ESMF\_GridComp} execution.
! \item[{[comptype]}]
!   Return the Component type.
!   See section \ref{const:comptype} for a complete list of valid flags.
! \item[{[vmIsPresent]}]
!   {\tt .true.} if {\tt vm} was set in GridComp object,
!   {\tt .false.} otherwise.
! \item[{[vm]}]
!   Return the associated VM.
!   It is an error to query for the VM if none is associated with
!   the GridComp. If unsure, get {\tt vmIsPresent} first to determine
!   the status.
! \item[{[name]}]
!   Return the name of the {\tt ESMF\_GridComp}.
! \item[{[rc]}]
!   Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOP
!------------------------------------------------------------------------------
    integer               :: localrc      ! local return code
    type(ESMF_CompStatus) :: compStatus

    ! initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit,gridcomp,rc)

    ! call Comp method
    call ESMF_CompGet(gridcomp%compp, name=name, vm=vm, contextflag=contextflag,&
      grid=grid, gridList=gridList, mesh=mesh, meshList=meshList, &
      locstream=locstream, locstreamList=locstreamList, &
      xgrid=xgrid, xgridList=xgridList, &
      importState=importState, exportState=exportState, clock=clock,&
      configFile=configFile, config=config, currentMethod=currentMethod, &
      currentPhase=currentPhase, localPet=localPet, petCount=petCount, &
      comptype=comptype, compStatus=compStatus, rc=localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    if (gridcomp%isNamedAlias .and. present(name)) then
      ! access NamedAlias name
      name = trim(gridcomp%name)
    endif

    ! call Comp method
    call ESMF_CompStatusGet(compStatus, &
      clockIsPresent = clockIsPresent, &
      configIsPresent = configIsPresent, &
      configFileIsPresent = configFileIsPresent, &
      vmIsPresent = vmIsPresent, &
      isIsPresent = importStateIsPresent, &
      esIsPresent = exportStateIsPresent, &
      gridIsPresent = gridIsPresent, &
      meshIsPresent = meshIsPresent, &
      locstreamIsPresent = locstreamIsPresent, &
      xgridIsPresent = xgridIsPresent, &
      rc = localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS
  end subroutine ESMF_GridCompGet
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompGetEPPhaseCount"
!BOPI
! !IROUTINE: ESMF_GridCompGetEPPhaseCount - Get number of phases of an entry point
!
! !INTERFACE:
  subroutine ESMF_GridCompGetEPPhaseCount(gridcomp, methodflag, phaseCount, &
    phaseZeroFlag, rc)

! !ARGUMENTS:
    type(ESMF_GridComp),    intent(in)            :: gridcomp
    type(ESMF_Method_Flag), intent(in)            :: methodflag
    integer,                intent(out)           :: phaseCount
    logical,                intent(out), optional :: phaseZeroFlag
    integer,                intent(out), optional :: rc
!
! !DESCRIPTION:
! Get phaseCount
!
! The arguments are:
! \begin{description}
! \item[gridcomp]
!   An {\tt ESMF\_GridComp} object.
! \item[methodflag]
!   \begin{sloppypar}
!   One of a set of predefined Component methods - e.g.
!   {\tt ESMF\_METHOD\_INITIALIZE}, {\tt ESMF\_METHOD\_RUN},
!   {\tt ESMF\_METHOD\_FINALIZE}. See section \ref{const:method}
!   for a complete list of valid method options.
!   \end{sloppypar}
! \item[phaseCount]
!   The number of phases for {\tt methodflag}. The method has 1..phaseCount phases.
! \item[phaseZeroFlag]
!   Return .true. if a "zero" phase was registered for {\tt methodflag}. Otherwise
!   return .false..
! \item[{[rc]}]
!   Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOPI
!------------------------------------------------------------------------------
    integer :: localrc                       ! local error status
    type(ESMF_Logical)::  phaseZeroFlagHelp

    ! initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit, gridcomp, rc)

    call c_ESMC_GetEntryPointPhaseCount(gridcomp, methodflag, phaseCount, &
      phaseZeroFlagHelp, localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! translate ESMF_Logical -> logical
    if (present(phaseZeroFlag)) then
      phaseZeroFlag = phaseZeroFlagHelp
    endif

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS
  end subroutine ESMF_GridCompGetEPPhaseCount
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
!BOP
! !IROUTINE: ESMF_GridCompGetInternalState - Get private data block pointer
!
! !INTERFACE:
! subroutine ESMF_GridCompGetInternalState(gridcomp, wrappedDataPointer, rc)
!
! !ARGUMENTS:
!   type(ESMF_GridComp)             :: gridcomp
!   type(wrapper)                   :: wrappedDataPointer
!   integer,            intent(out) :: rc
!
! !STATUS:
! \begin{itemize}
! \item\apiStatusCompatibleVersion{5.2.0r}
! \end{itemize}
!
! !DESCRIPTION:
! Available to be called by an {\tt ESMF\_GridComp} at any time after
! {\tt ESMF\_GridCompSetInternalState} has been called.
! Since init, run, and finalize must be separate subroutines, data that
! they need to share in common can either be module global data, or can
! be allocated in a private data block and the address of that block
! can be registered with the framework and retrieved by this call.
! When running multiple instantiations of an {\tt ESMF\_GridComp},
! for example during ensemble runs,
! it may be simpler to maintain private data specific to
! each run with private data blocks.  A corresponding
! {\tt ESMF\_GridCompSetInternalState} call sets the data pointer to
! this block, and this call retrieves the data pointer.
! Note that the {\tt wrappedDataPointer} argument needs to be a derived type
! which contains only a pointer of the type of the data block defined
! by the user.  When making this call the pointer needs to be unassociated.
! When the call returns, the pointer will now reference the original
! data block which was set during the previous call to
! {\tt ESMF\_GridCompSetInternalState}.
!
! Only the {\em last} data block set via
! {\tt ESMF\_GridCompSetInternalState} will be accessible.
!
! CAUTION: If you are working with a compiler that does not support Fortran 2018
! assumed-type dummy arguments, then this method does not have an explicit
! Fortran interface. In this case do not specify argument keywords when calling
! this method!
!
! The arguments are:
! \begin{description}
! \item[gridcomp]
!   An {\tt ESMF\_GridComp} object.
! \item[wrappedDataPointer]
!   A derived type (wrapper), containing only an unassociated pointer
!   to the private data block.
!   The framework will fill in the pointer. When this call returns, the
!   pointer is set to the same address set during the last
!   {\tt ESMF\_GridCompSetInternalState} call.
!   This level of indirection is needed to reliably set and retrieve
!   the data block no matter which architecture or compiler is used.
! \item[rc]
!   Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
!   Note: unlike most other ESMF routines, this argument is not optional
!   because of implementation considerations.
! \end{description}
!
!EOP
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompInitialize"
!BOP
! !IROUTINE: ESMF_GridCompInitialize - Call the GridComp's initialize routine

! !INTERFACE:
  recursive subroutine ESMF_GridCompInitialize(gridcomp, keywordEnforcer, &
    importState, exportState, clock, syncflag, phase, timeout, timeoutFlag, &
    userRc, rc)
!
! !ARGUMENTS:
    type(ESMF_GridComp),  intent(inout)           :: gridcomp
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    type(ESMF_State),     intent(inout), optional :: importState
    type(ESMF_State),     intent(inout), optional :: exportState
    type(ESMF_Clock),     intent(inout), optional :: clock
    type(ESMF_Sync_Flag), intent(in),    optional :: syncflag
    integer,              intent(in),    optional :: phase
    integer,              intent(in),    optional :: timeout
    logical,              intent(out),   optional :: timeoutFlag
    integer,              intent(out),   optional :: userRc
    integer,              intent(out),   optional :: rc
!
! !STATUS:
! \begin{itemize}
! \item\apiStatusCompatibleVersion{5.2.0r}
! \item\apiStatusModifiedSinceVersion{5.2.0r}
! \begin{description}
! \item[5.3.0] Added argument {\tt timeout}.
!              Added argument {\tt timeoutFlag}.
!              The new arguments provide access to the fault-tolerant component
!              features.
! \end{description}
! \end{itemize}
!
! !DESCRIPTION:
! Call the associated user initialization routine for
! an {\tt ESMF\_GridComp}.
!
! The arguments are:
! \begin{description}
! \item[gridcomp]
!   {\tt ESMF\_GridComp} to call initialize routine for.
! \item[{[importState]}]
!   {\tt ESMF\_State} containing import data for coupling. If not present, a dummy
!   argument will be passed to the user-supplied routine.  The
!   importState argument in the user code cannot be optional.
! \item[{[exportState]}]
!   {\tt ESMF\_State} containing export data for coupling. If not present, a dummy
!   argument will be passed to the user-supplied routine.  The
!   exportState argument in the user code cannot be optional.
! \item[{[clock]}]
!   External {\tt ESMF\_Clock} for passing in time information.
!   This is generally the parent component's clock, and will be treated
!   as read-only by the child component.  The child component can maintain
!   a private clock for its own internal time computations. If not present, a dummy
!   argument will be passed to the user-supplied routine.  The
!   clock argument in the user code cannot be optional.
! \item[{[syncflag]}]
!   Blocking behavior of this method call. See section \ref{const:sync}
!   for a list of valid blocking options. Default option is
!   {\tt ESMF\_SYNC\_VASBLOCKING} which blocks PETs and their spawned off threads
!   across each VAS but does not synchronize PETs that run in different VASs.
! \item[{[phase]}]
!   Component providers must document whether each of their
!   routines are {\em single-phase} or {\em multi-phase}.
!   Single-phase routines require only one invocation to complete
!   their work.
!   Multi-phase routines provide multiple subroutines to accomplish
!   the work, accommodating components which must complete part of their
!   work, return to the caller and allow other processing to occur,
!   and then continue the original operation.
!   For multiple-phase child components, this is the integer phase
!   number to be invoked.
!   For single-phase child components this argument is optional. The default is
!   1.
! \item[{[timeout]}]
!   The maximum period in seconds that this call will wait in communications
!   with the actual component, before returning with a timeout condition.
!   The default is 3600, i.e. 1 hour. The {\tt timeout} argument is only
!   supported for connected dual components.
! \item[{[timeoutFlag]}]
!   Returns {\tt .true.} if the timeout was reached, {\tt .false.} otherwise.
!   If {\tt timeoutFlag} was {\em not} provided, a timeout condition will lead
!   to a return code of {\tt rc \textbackslash = ESMF\_SUCCESS}. Otherwise the
!   return value of {\tt timeoutFlag} is the sole indicator of a timeout
!   condition.
! \item[{[userRc]}]
!   Return code set by {\tt userRoutine} before returning.
! \item[{[rc]}]
!   Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOP
!------------------------------------------------------------------------------
    integer :: localrc                        ! local return code
    integer :: timeoutArg

    ! initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit,gridcomp,rc)

    ! check consistency between timeout argument and component argument
    if (present(timeout).and. &
      .not.ESMF_CompIsDualConnected(gridcomp%compp, rc=localrc)) then
      call ESMF_LogSetError(ESMF_RC_ARG_INCOMP, &
        msg="'timeout' argument is only allowed for connected dual components",&
        ESMF_CONTEXT, rcToReturn=rc)
      return
    endif

    timeoutArg = ESMF_DEFAULT_TIMEOUT ! default 1h
    if (present(timeout)) timeoutArg = timeout

    ! call Comp method
    call ESMF_CompExecute(gridcomp%compp, method=ESMF_METHOD_INITIALIZEIC, &
      importState=importState, exportState=exportState, clock=clock, &
      syncflag=syncflag, phase=phase, timeout=timeoutArg, &
      userRc=userRc, rc=localrc)
    ! conditionally filter out the RC_TIMEOUT and return success
    if (present(timeoutFlag)) then
      timeoutFlag = .false. ! initialize
      if ((localrc==ESMF_RC_TIMEOUT).or.(localrc==ESMC_RC_TIMEOUT)) then
        timeoutFlag = .true.      ! indicate timeout through flag argument
        localrc = ESMF_SUCCESS    ! do not raise error condition on user level
      endif
    endif
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS
  end subroutine ESMF_GridCompInitialize
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompInitializeAct"
!BOPI
! !IROUTINE: ESMF_GridCompInitializeAct - Call the GridComp's initialize routine

! !INTERFACE:
  recursive subroutine ESMF_GridCompInitializeAct(gridcomp, importState, &
    exportState, clock, syncflag, phase, userRc, rc)
!
! !ARGUMENTS:
    type(ESMF_GridComp),  intent(inout)           :: gridcomp
    type(ESMF_State),     intent(inout), optional :: importState
    type(ESMF_State),     intent(inout), optional :: exportState
    type(ESMF_Clock),     intent(inout), optional :: clock
    type(ESMF_Sync_Flag), intent(in),    optional :: syncflag
    integer,              intent(in),    optional :: phase
    integer,              intent(out),   optional :: userRc
    integer,              intent(out),   optional :: rc
!
! !DESCRIPTION:
! Same as {\tt ESMF\_GridCompInitialize} but no redirection through the
! Interface Component method, instead directly call into the actual method.
!
!EOPI
!------------------------------------------------------------------------------
    integer :: localrc                        ! local return code

    ! initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit,gridcomp,rc)

    ! call Comp method
    call ESMF_CompExecute(gridcomp%compp, method=ESMF_METHOD_INITIALIZE, &
      importState=importState, exportState=exportState, clock=clock, &
      syncflag=syncflag, phase=phase, userRc=userRc, rc=localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS
  end subroutine ESMF_GridCompInitializeAct
!------------------------------------------------------------------------------


! -------------------------- ESMF-public method -------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompIsCreated()"
!BOP
! !IROUTINE: ESMF_GridCompIsCreated - Check whether a GridComp object has been created

! !INTERFACE:
  function ESMF_GridCompIsCreated(gridcomp, keywordEnforcer, rc)
! !RETURN VALUE:
    logical :: ESMF_GridCompIsCreated
!
! !ARGUMENTS:
    type(ESMF_GridComp), intent(in)            :: gridcomp
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    integer,             intent(out), optional :: rc

! !DESCRIPTION:
!   Return {\tt .true.} if the {\tt gridcomp} has been created. Otherwise return
!   {\tt .false.}. If an error occurs, i.e. {\tt rc /= ESMF\_SUCCESS} is
!   returned, the return value of the function will also be {\tt .false.}.
!
! The arguments are:
!   \begin{description}
!   \item[gridcomp]
!     {\tt ESMF\_GridComp} queried.
!   \item[{[rc]}]
!     Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
!   \end{description}
!
!EOP
  !-----------------------------------------------------------------------------
    ESMF_GridCompIsCreated = .false.   ! initialize
    if (present(rc)) rc = ESMF_SUCCESS
    if (ESMF_GridCompGetInit(gridcomp)==ESMF_INIT_CREATED) &
      ESMF_GridCompIsCreated = .true.
  end function
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompIsPetLocal"
!BOP
! !IROUTINE: ESMF_GridCompIsPetLocal - Inquire if this GridComp is to execute on the calling PET
!
! !INTERFACE:
  recursive function ESMF_GridCompIsPetLocal(gridcomp, keywordEnforcer, rc)
!
! !RETURN VALUE:
    logical :: ESMF_GridCompIsPetLocal
!
! !ARGUMENTS:
    type(ESMF_GridComp), intent(in)            :: gridcomp
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    integer,             intent(out), optional :: rc
!
! !STATUS:
! \begin{itemize}
! \item\apiStatusCompatibleVersion{5.2.0r}
! \end{itemize}
!
! !DESCRIPTION:
! Inquire if this {\tt ESMF\_GridComp} object is to execute on the calling PET.
!
! The return value is {\tt .true.} if the component is to execute on the
! calling PET, {\tt .false.} otherwise.
!
! The arguments are:
! \begin{description}
! \item[gridcomp]
!   {\tt ESMF\_GridComp} queried.
! \item[{[rc]}]
!   Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOP
!------------------------------------------------------------------------------
    integer :: localrc                     ! local error status
    logical :: localresult

    ! initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
        localrc = ESMF_RC_NOT_IMPL

    ! Initialize output value in case of error
    ESMF_GridCompIsPetLocal = .false.

    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit,gridcomp,rc)

    ! call Comp method
    localresult = ESMF_CompIsPetLocal(gridcomp%compp, rc=localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ESMF_GridCompIsPetLocal = localresult

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS
  end function ESMF_GridCompIsPetLocal
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompPrint"
!BOP
! !IROUTINE:  ESMF_GridCompPrint - Print GridComp information
!
! !INTERFACE:
  subroutine ESMF_GridCompPrint(gridcomp, keywordEnforcer, rc)
!
! !ARGUMENTS:
    type(ESMF_GridComp), intent(in)            :: gridcomp
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    integer,             intent(out), optional :: rc
!
! !STATUS:
! \begin{itemize}
! \item\apiStatusCompatibleVersion{5.2.0r}
! \end{itemize}
!
! !DESCRIPTION:
! Prints information about an {\tt ESMF\_GridComp} to {\tt stdout}. \\
!
! The arguments are:
! \begin{description}
! \item[gridcomp]
!   {\tt ESMF\_GridComp} to print.
! \item[{[rc]}]
!   Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOP
!------------------------------------------------------------------------------
    integer :: localrc                        ! local return code

    ! initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit,gridcomp,rc)

    write (ESMF_UtilIOStdout,*) "Gridded Component:"
    ! call Comp method
    call ESMF_CompPrint(gridcomp%compp, rc=localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS
  end subroutine ESMF_GridCompPrint
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompReadRestart"
!BOP
! !IROUTINE: ESMF_GridCompReadRestart - Call the GridComp's read restart routine
!
! !INTERFACE:
  recursive subroutine ESMF_GridCompReadRestart(gridcomp, keywordEnforcer, &
    importState, exportState, clock, syncflag, phase, timeout, timeoutFlag, &
    userRc, rc)
!
! !ARGUMENTS:
    type(ESMF_GridComp),  intent(inout)           :: gridcomp
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    type(ESMF_State),     intent(inout), optional :: importState
    type(ESMF_State),     intent(inout), optional :: exportState
    type(ESMF_Clock),     intent(inout), optional :: clock
    type(ESMF_Sync_Flag), intent(in),    optional :: syncflag
    integer,              intent(in),    optional :: phase
    integer,              intent(in),    optional :: timeout
    logical,              intent(out),   optional :: timeoutFlag
    integer,              intent(out),   optional :: userRc
    integer,              intent(out),   optional :: rc
!
! !STATUS:
! \begin{itemize}
! \item\apiStatusCompatibleVersion{5.2.0r}
! \item\apiStatusModifiedSinceVersion{5.2.0r}
! \begin{description}
! \item[5.3.0] Added argument {\tt timeout}.
!              Added argument {\tt timeoutFlag}.
!              The new arguments provide access to the fault-tolerant component
!              features.
! \end{description}
! \end{itemize}
!
! !DESCRIPTION:
! Call the associated user read restart routine for
! an {\tt ESMF\_GridComp}.
!
! The arguments are:
! \begin{description}
! \item[gridcomp]
!   {\tt ESMF\_GridComp} to call run routine for.
! \item[{[importState]}]
!   {\tt ESMF\_State} containing import data. If not present, a dummy
!   argument will be passed to the user-supplied routine.  The
!   importState argument in the user code cannot be optional.
! \item[{[exportState]}]
!   {\tt ESMF\_State} containing export data. If not present, a dummy
!   argument will be passed to the user-supplied routine.  The
!   exportState argument in the user code cannot be optional.
! \item[{[clock]}]
!   External {\tt ESMF\_Clock} for passing in time information.
!   This is generally the parent component's clock, and will be treated
!   as read-only by the child component.  The child component can maintain
!   a private clock for its own internal time computations. If not present, a dummy
!   argument will be passed to the user-supplied routine.  The
!   clock argument in the user code cannot be optional.
! \item[{[syncflag]}]
!   Blocking behavior of this method call. See section \ref{const:sync}
!   for a list of valid blocking options. Default option is
!   {\tt ESMF\_SYNC\_VASBLOCKING} which blocks PETs and their spawned off threads
!   across each VAS but does not synchronize PETs that run in different VASs.
! \item[{[phase]}]
!   Component providers must document whether each of their
!   routines are {\em single-phase} or {\em multi-phase}.
!   Single-phase routines require only one invocation to complete
!   their work.
!   Multi-phase routines provide multiple subroutines to accomplish
!   the work, accommodating components which must complete part of their
!   work, return to the caller and allow other processing to occur,
!   and then continue the original operation.
!   For multiple-phase child components, this is the integer phase
!   number to be invoked.
!   For single-phase child components this argument is optional. The default is
!   1.
! \item[{[timeout]}]
!   The maximum period in seconds that this call will wait in communications
!   with the actual component, before returning with a timeout condition.
!   The default is 3600, i.e. 1 hour. The {\tt timeout} argument is only
!   supported for connected dual components.
! \item[{[timeoutFlag]}]
!   Returns {\tt .true.} if the timeout was reached, {\tt .false.} otherwise.
!   If {\tt timeoutFlag} was {\em not} provided, a timeout condition will lead
!   to a return code of {\tt rc \textbackslash = ESMF\_SUCCESS}. Otherwise the
!   return value of {\tt timeoutFlag} is the sole indicator of a timeout
!   condition.
! \item[{[userRc]}]
!   Return code set by {\tt userRoutine} before returning.
! \item[{[rc]}]
!   Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOP
!------------------------------------------------------------------------------
    integer :: localrc                        ! local return code
    integer :: timeoutArg

    ! initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit,gridcomp,rc)

    ! check consistency between timeout argument and component argument
    if (present(timeout).and. &
      .not.ESMF_CompIsDualConnected(gridcomp%compp, rc=localrc)) then
      call ESMF_LogSetError(ESMF_RC_ARG_INCOMP, &
        msg="'timeout' argument is only allowed for connected dual components",&
        ESMF_CONTEXT, rcToReturn=rc)
      return
    endif

    timeoutArg = ESMF_DEFAULT_TIMEOUT ! default 1h
    if (present(timeout)) timeoutArg = timeout

    ! call Comp method
    call ESMF_CompExecute(gridcomp%compp, method=ESMF_METHOD_READRESTART, &
      importState=importState, exportState=exportState, clock=clock, &
      syncflag=syncflag, phase=phase, timeout=timeoutArg, &
      userRc=userRc, rc=localrc)
    ! conditionally filter out the RC_TIMEOUT and return success
    if (present(timeoutFlag)) then
      timeoutFlag = .false. ! initialize
      if ((localrc==ESMF_RC_TIMEOUT).or.(localrc==ESMC_RC_TIMEOUT)) then
        timeoutFlag = .true.      ! indicate timeout through flag argument
        localrc = ESMF_SUCCESS    ! do not raise error condition on user level
      endif
    endif
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS
  end subroutine ESMF_GridCompReadRestart
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompRun"
!BOP
! !IROUTINE: ESMF_GridCompRun - Call the GridComp's run routine
!
! !INTERFACE:
  recursive subroutine ESMF_GridCompRun(gridcomp, keywordEnforcer, &
    importState, exportState, clock, syncflag, phase, timeout, timeoutFlag, &
    userRc, rc)
!
! !ARGUMENTS:
    type(ESMF_GridComp),  intent(inout)           :: gridcomp
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    type(ESMF_State),     intent(inout), optional :: importState
    type(ESMF_State),     intent(inout), optional :: exportState
    type(ESMF_Clock),     intent(inout), optional :: clock
    type(ESMF_Sync_Flag), intent(in),    optional :: syncflag
    integer,              intent(in),    optional :: phase
    integer,              intent(in),    optional :: timeout
    logical,              intent(out),   optional :: timeoutFlag
    integer,              intent(out),   optional :: userRc
    integer,              intent(out),   optional :: rc
!
! !STATUS:
! \begin{itemize}
! \item\apiStatusCompatibleVersion{5.2.0r}
! \item\apiStatusModifiedSinceVersion{5.2.0r}
! \begin{description}
! \item[5.3.0] Added argument {\tt timeout}.
!              Added argument {\tt timeoutFlag}.
!              The new arguments provide access to the fault-tolerant component
!              features.
! \end{description}
! \end{itemize}
!
! !DESCRIPTION:
! Call the associated user run routine for
! an {\tt ESMF\_GridComp}.
!
! The arguments are:
! \begin{description}
! \item[gridcomp]
!   {\tt ESMF\_GridComp} to call run routine for.
! \item[{[importState]}]
!   {\tt ESMF\_State} containing import data. If not present, a dummy
!   argument will be passed to the user-supplied routine.  The
!   importState argument in the user code cannot be optional.
! \item[{[exportState]}]
!   {\tt ESMF\_State} containing export data. If not present, a dummy
!   argument will be passed to the user-supplied routine.  The
!   exportState argument in the user code cannot be optional.
! \item[{[clock]}]
!   External {\tt ESMF\_Clock} for passing in time information.
!   This is generally the parent component's clock, and will be treated
!   as read-only by the child component.  The child component can maintain
!   a private clock for its own internal time computations. If not present, a dummy
!   argument will be passed to the user-supplied routine.  The
!   clock argument in the user code cannot be optional.
! \item[{[syncflag]}]
!   Blocking behavior of this method call. See section \ref{const:sync}
!   for a list of valid blocking options. Default option is
!   {\tt ESMF\_SYNC\_VASBLOCKING} which blocks PETs and their spawned off threads
!   across each VAS but does not synchronize PETs that run in different VASs.
! \item[{[phase]}]
!   Component providers must document whether each of their
!   routines are {\em single-phase} or {\em multi-phase}.
!   Single-phase routines require only one invocation to complete
!   their work.
!   Multi-phase routines provide multiple subroutines to accomplish
!   the work, accommodating components which must complete part of their
!   work, return to the caller and allow other processing to occur,
!   and then continue the original operation.
!   For multiple-phase child components, this is the integer phase
!   number to be invoked.
!   For single-phase child components this argument is optional. The default is
!   1.
! \item[{[timeout]}]
!   The maximum period in seconds that this call will wait in communications
!   with the actual component, before returning with a timeout condition.
!   The default is 3600, i.e. 1 hour. The {\tt timeout} argument is only
!   supported for connected dual components.
! \item[{[timeoutFlag]}]
!   Returns {\tt .true.} if the timeout was reached, {\tt .false.} otherwise.
!   If {\tt timeoutFlag} was {\em not} provided, a timeout condition will lead
!   to a return code of {\tt rc \textbackslash = ESMF\_SUCCESS}. Otherwise the
!   return value of {\tt timeoutFlag} is the sole indicator of a timeout
!   condition.
! \item[{[userRc]}]
!   Return code set by {\tt userRoutine} before returning.
! \item[{[rc]}]
!   Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOP
!------------------------------------------------------------------------------
    integer :: localrc                        ! local return code
    integer :: timeoutArg

    ! initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit,gridcomp,rc)

    ! check consistency between timeout argument and component argument
    if (present(timeout).and. &
      .not.ESMF_CompIsDualConnected(gridcomp%compp, rc=localrc)) then
      call ESMF_LogSetError(ESMF_RC_ARG_INCOMP, &
        msg="'timeout' argument is only allowed for connected dual components",&
        ESMF_CONTEXT, rcToReturn=rc)
      return
    endif

    timeoutArg = ESMF_DEFAULT_TIMEOUT ! default 1h
    if (present(timeout)) timeoutArg = timeout

    ! call Comp method
    call ESMF_CompExecute(gridcomp%compp, method=ESMF_METHOD_RUNIC, &
      importState=importState, exportState=exportState, clock=clock, &
      syncflag=syncflag, phase=phase, timeout=timeoutArg, &
      userRc=userRc, rc=localrc)
    ! conditionally filter out the RC_TIMEOUT and return success
    if (present(timeoutFlag)) then
      timeoutFlag = .false. ! initialize
      if ((localrc==ESMF_RC_TIMEOUT).or.(localrc==ESMC_RC_TIMEOUT)) then
        timeoutFlag = .true.      ! indicate timeout through flag argument
        localrc = ESMF_SUCCESS    ! do not raise error condition on user level
      endif
    endif
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS
  end subroutine ESMF_GridCompRun
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompRunAct"
!BOPI
! !IROUTINE: ESMF_GridCompRunAct - Call the GridComp's run routine
!
! !INTERFACE:
  recursive subroutine ESMF_GridCompRunAct(gridcomp, importState, exportState,&
    clock, syncflag, phase, userRc, rc)
!
! !ARGUMENTS:
    type(ESMF_GridComp),  intent(inout)           :: gridcomp
    type(ESMF_State),     intent(inout), optional :: importState
    type(ESMF_State),     intent(inout), optional :: exportState
    type(ESMF_Clock),     intent(inout), optional :: clock
    type(ESMF_Sync_Flag), intent(in),    optional :: syncflag
    integer,              intent(in),    optional :: phase
    integer,              intent(out),   optional :: userRc
    integer,              intent(out),   optional :: rc
!
! !DESCRIPTION:
! Same as {\tt ESMF\_GridCompRun} but no redirection through the
! Interface Component method, instead directly call into the actual method.
!
!EOPI
!------------------------------------------------------------------------------
    integer :: localrc                        ! local return code

    ! initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit,gridcomp,rc)

    ! call Comp method
    call ESMF_CompExecute(gridcomp%compp, method=ESMF_METHOD_RUN, &
      importState=importState, exportState=exportState, clock=clock, &
      syncflag=syncflag, phase=phase, userRc=userRc, rc=localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS
  end subroutine ESMF_GridCompRunAct
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompServiceLoop"
!BOP
! !IROUTINE: ESMF_GridCompServiceLoop - Call the GridComp's service loop routine

! !INTERFACE:
  recursive subroutine ESMF_GridCompServiceLoop(gridcomp, keywordEnforcer, &
    importState, exportState, clock, syncflag, port, timeout, timeoutFlag, rc)
!
! !ARGUMENTS:
    type(ESMF_GridComp),  intent(inout)           :: gridcomp
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    type(ESMF_State),     intent(inout), optional :: importState
    type(ESMF_State),     intent(inout), optional :: exportState
    type(ESMF_Clock),     intent(inout), optional :: clock
    type(ESMF_Sync_Flag), intent(in),    optional :: syncflag
    integer,              intent(in),    optional :: port
    integer,              intent(in),    optional :: timeout
    logical,              intent(out),   optional :: timeoutFlag
    integer,              intent(out),   optional :: rc
!
! !DESCRIPTION:
! Call the ServiceLoop routine for an {\tt ESMF\_GridComp}.
! This tries to establish a "component tunnel" between the {\em actual}
! Component (calling this routine) and a {\tt dual} Component connecting to it
! through a matching SetServices call.
!
! The arguments are:
! \begin{description}
! \item[gridcomp]
!   {\tt ESMF\_GridComp} to call service loop routine for.
! \item[{[importState]}]
!   {\tt ESMF\_State} containing import data for coupling. If not present, a dummy
!   argument will be passed to the user-supplied routine.  The
!   importState argument in the user code cannot be optional.
! \item[{[exportState]}]
!   {\tt ESMF\_State} containing export data for coupling. If not present, a dummy
!   argument will be passed to the user-supplied routine.  The
!   exportState argument in the user code cannot be optional.
! \item[{[clock]}]
!   External {\tt ESMF\_Clock} for passing in time information.
!   This is generally the parent component's clock, and will be treated
!   as read-only by the child component.  The child component can maintain
!   a private clock for its own internal time computations. If not present, a dummy
!   argument will be passed to the user-supplied routine.  The
!   clock argument in the user code cannot be optional.
! \item[{[syncflag]}]
!   Blocking behavior of this method call. See section \ref{const:sync}
!   for a list of valid blocking options. Default option is
!   {\tt ESMF\_SYNC\_VASBLOCKING} which blocks PETs and their spawned off threads
!   across each VAS but does not synchronize PETs that run in different VASs.
! \item[{[port]}]
!   In case a port number is provided, the "component tunnel" is established
!   using sockets. The actual component side, i.e. the side that calls into
!   {\tt ESMF\_GridCompServiceLoop()}, starts to listen on the specified port
!   as the server. The valid port range is [1024, 65535].
!   In case the {\tt port} argument is {\em not} specified, the "component
!   tunnel" is established within the same executable using local communication
!   methods (e.g. MPI).
! \item[{[timeout]}]
!   The maximum period in seconds that this call will wait for communications
!   with the dual component, before returning with a timeout condition.
!   The default is 3600, i.e. 1 hour.
!   (NOTE: Currently this option is only available for socket based component
!   tunnels.)
! \item[{[timeoutFlag]}]
!   Returns {\tt .true.} if the timeout was reached, {\tt .false.} otherwise.
!   If {\tt timeoutFlag} was {\em not} provided, a timeout condition will lead
!   to a return code of {\tt rc \textbackslash = ESMF\_SUCCESS}. Otherwise the
!   return value of {\tt timeoutFlag} is the sole indicator of a timeout
!   condition.
! \item[{[rc]}]
!   Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOP
!------------------------------------------------------------------------------
    integer :: localrc                        ! local return code
    integer :: localrc2                       ! local return code
    integer :: timeoutArg

    ! initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit,gridcomp,rc)

    if (.not.present(port).and.(present(timeout))) then
      call ESMF_LogSetError(ESMF_RC_ARG_INCOMP, &
        msg="Currently the 'timeout' argument requires the 'port' argument", &
        ESMF_CONTEXT, rcToReturn=rc)
      return  ! bail out
    endif

    timeoutArg = ESMF_DEFAULT_TIMEOUT ! default 1h
    if (present(timeout)) timeoutArg = timeout

    ! call Comp method
    call ESMF_CompExecute(gridcomp%compp, method=ESMF_METHOD_SERVICELOOP, &
      importState=importState, exportState=exportState, clock=clock, &
      syncflag=syncflag, port=port, timeout=timeoutArg, userRc=localrc2, &
      rc=localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return
    ! ESMF_METHOD_SERVICELOOP is a framework internal method, therefore
    ! the code returned in userRc is a framework internal return code and must
    ! be treated as such. However, the treatment of RC_TIMEOUT depends
    ! on the presence/absence of timeoutFlag.
    if (present(timeoutFlag)) then
      timeoutFlag = .false. ! initialize
      if ((localrc2==ESMF_RC_TIMEOUT).or.(localrc2==ESMC_RC_TIMEOUT)) then
        timeoutFlag = .true.      ! indicate timeout through flag argument
        localrc2 = ESMF_SUCCESS   ! do not raise error condition on user level
      endif
    endif
    if (ESMF_LogFoundError(localrc2, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS
  end subroutine ESMF_GridCompServiceLoop
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompSet"
!BOP
! !IROUTINE: ESMF_GridCompSet - Set or reset information about the GridComp
!
! !INTERFACE:
  subroutine ESMF_GridCompSet(gridcomp, keywordEnforcer, grid, gridList, &
    mesh, meshList, locstream, locstreamList, xgrid, xgridList, &
    config, configFile, clock, name, rc)
!
! !ARGUMENTS:
    type(ESMF_GridComp),    intent(inout)         :: gridcomp
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    type(ESMF_Grid),        intent(in),  optional :: grid
    type(ESMF_Grid),        intent(in),  optional :: gridList(:)
    type(ESMF_Mesh),        intent(in),  optional :: mesh
    type(ESMF_Mesh),        intent(in),  optional :: meshList(:)
    type(ESMF_LocStream),   intent(in),  optional :: locstream
    type(ESMF_LocStream),   intent(in),  optional :: locstreamList(:)
    type(ESMF_XGrid),       intent(in),  optional :: xgrid
    type(ESMF_XGrid),       intent(in),  optional :: xgridList(:)
    type(ESMF_Config),      intent(in),  optional :: config
    character(len=*),       intent(in),  optional :: configFile
    type(ESMF_Clock),       intent(in),  optional :: clock
    character(len=*),       intent(in),  optional :: name
    integer,                intent(out), optional :: rc
!
! !STATUS:
! \begin{itemize}
! \item\apiStatusCompatibleVersion{5.2.0r}
! \item\apiStatusModifiedSinceVersion{5.2.0r}
! \begin{description}
! \begin{sloppypar}
! \item[7.1.0r] Added arguments {\tt gridList}, {\tt mesh}, {\tt meshList},
!   {\tt locstream}, {\tt locstreamList}, {\tt xgrid}, and {\tt xgridList}.
!   These arguments add support for holding references to multiple geom objects,
!   either of the same type, or different type, in the same
!   {\tt ESMF\_GridComp} object.
! \end{sloppypar}
! \end{description}
! \end{itemize}
!
! !DESCRIPTION:
! Sets or resets information about an {\tt ESMF\_GridComp}.
!
! The arguments are:
! \begin{description}
! \item[gridcomp]
!   {\tt ESMF\_GridComp} to change.
! \item[{[grid]}]
!   Associate an {\tt ESMF\_Grid} object with the {\tt gridcomp} component.
!   This is simply a convenience feature for the user. The ESMF library code
!   does not access the {\tt grid} object.
!   The {\tt grid} argument is mutually exclusive with the {\tt gridList}
!   argument. If both arguments are provided, the routine will fail, and an
!   error is returned in {\tt rc}.
!   By default, i.e. if neither {\tt grid} nor {\tt gridList} are provided,
!   the {\tt ESMF\_Grid} association of the incoming {\tt gridcomp}
!   component remains unchanged.
! \item[{[gridList]}]
!   Associate a list of {\tt ESMF\_Grid} objects with the {\tt gridcomp}
!   component.
!   This is simply a convenience feature for the user. The ESMF library code
!   does not access the {\tt gridList} object.
!   The {\tt gridList} argument is mutually exclusive with the {\tt grid}
!   argument. If both arguments are provided, the routine will fail, and an
!   error is returned in {\tt rc}.
!   By default, i.e. if neither {\tt grid} nor {\tt gridList} are provided,
!   the {\tt ESMF\_Grid} association of the incoming {\tt gridcomp}
!   component remains unchanged.
! \item[{[mesh]}]
!   Associate an {\tt ESMF\_Mesh} object with the {\tt gridcomp} component.
!   This is simply a convenience feature for the user. The ESMF library code
!   does not access the {\tt mesh} object.
!   The {\tt mesh} argument is mutually exclusive with the {\tt meshList}
!   argument. If both arguments are provided, the routine will fail, and an
!   error is returned in {\tt rc}.
!   By default, i.e. if neither {\tt mesh} nor {\tt meshList} are provided,
!   the {\tt ESMF\_Mesh} association of the incoming {\tt gridcomp}
!   component remains unchanged.
! \item[{[meshList]}]
!   Associate a list of {\tt ESMF\_Mesh} objects with the {\tt gridcomp}
!   component.
!   This is simply a convenience feature for the user. The ESMF library code
!   does not access the {\tt meshList} object.
!   The {\tt meshList} argument is mutually exclusive with the {\tt mesh}
!   argument. If both arguments are provided, the routine will fail, and an
!   error is returned in {\tt rc}.
!   By default, i.e. if neither {\tt mesh} nor {\tt meshList} are provided,
!   the {\tt ESMF\_Mesh} association of the incoming {\tt gridcomp}
!   component remains unchanged.
! \item[{[locstream]}]
!   Associate an {\tt ESMF\_LocStream} object with the {\tt gridcomp} component.
!   This is simply a convenience feature for the user. The ESMF library code
!   does not access the {\tt locstream} object.
!   The {\tt locstream} argument is mutually exclusive with the
!   {\tt locstreamList}
!   argument. If both arguments are provided, the routine will fail, and an
!   error is returned in {\tt rc}.
!   By default, i.e. if neither {\tt locstream} nor {\tt locstreamList} are
!   provided, the {\tt ESMF\_LocStream} association of the incoming
!   {\tt gridcomp} component remains unchanged.
! \item[{[locstreamList]}]
!   Associate a list of {\tt ESMF\_LocStream} objects with the {\tt gridcomp}
!   component.
!   This is simply a convenience feature for the user. The ESMF library code
!   does not access the {\tt locstreamList} object.
!   The {\tt locstreamList} argument is mutually exclusive with the
!   {\tt locstream}
!   argument. If both arguments are provided, the routine will fail, and an
!   error is returned in {\tt rc}.
!   By default, i.e. if neither {\tt locstream} nor {\tt locstreamList} are
!   provided, the {\tt ESMF\_LocStream} association of the incoming
!   {\tt gridcomp} component remains unchanged.
! \item[{[xgrid]}]
!   Associate an {\tt ESMF\_XGrid} object with the {\tt gridcomp} component.
!   This is simply a convenience feature for the user. The ESMF library code
!   does not access the {\tt xgrid} object.
!   The {\tt xgrid} argument is mutually exclusive with the {\tt xgridList}
!   argument. If both arguments are provided, the routine will fail, and an
!   error is returned in {\tt rc}.
!   By default, i.e. if neither {\tt xgrid} nor {\tt xgridList} are provided,
!   the {\tt ESMF\_XGrid} association of the incoming {\tt gridcomp}
!   component remains unchanged.
! \item[{[xgridList]}]
!   Associate a list of {\tt ESMF\_XGrid} objects with the {\tt gridcomp}
!   component.
!   This is simply a convenience feature for the user. The ESMF library code
!   does not access the {\tt xgridList} object.
!   The {\tt xgridList} argument is mutually exclusive with the {\tt xgrid}
!   argument. If both arguments are provided, the routine will fail, and an
!   error is returned in {\tt rc}.
!   By default, i.e. if neither {\tt xgrid} nor {\tt xgridList} are provided,
!   the {\tt ESMF\_XGrid} association of the incoming {\tt gridcomp}
!   component remains unchanged.
! \item[{[config]}]
!   An already-created {\tt ESMF\_Config} object to be attached to the
!   component.
!   If both {\tt config} and {\tt configFile} arguments are specified,
!   {\tt config} takes priority.
! \item[{[configFile]}]
!   The filename of an {\tt ESMF\_Config} format file.
!   If specified, a new {\tt ESMF\_Config} object is created and attached to the
!   component. The {\tt configFile} file is opened and associated
!   with the new config object.
!   If both {\tt config} and {\tt configFile} arguments are specified,
!   {\tt config} takes priority.
! \item[{[clock]}]
!   Set the private clock for this {\tt ESMF\_GridComp}.
! \item[{[name]}]
!   Set the name of the {\tt ESMF\_GridComp}.
! \item[{[rc]}]
!   Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOP
!------------------------------------------------------------------------------
    integer                         :: localrc           ! local return code

    ! initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit,gridcomp,rc)
    ESMF_INIT_CHECK_DEEP(ESMF_GridGetInit,grid,rc)
    ESMF_INIT_CHECK_DEEP(ESMF_ConfigGetInit,config,rc)
    ESMF_INIT_CHECK_DEEP(ESMF_ClockGetInit,clock,rc)

    if (gridcomp%isNamedAlias .and. present(name)) then
      ! set NamedAlias name
      gridcomp%name = trim(name)
      ! call Comp method (without name)
      call ESMF_CompSet(gridcomp%compp, &
        grid=grid, gridList=gridList, mesh=mesh, meshList=meshList, &
        locstream=locstream, locstreamList=locstreamList, xgrid=xgrid, &
        xgridList=xgridList, clock=clock, configFile=configFile, config=config, &
        rc=localrc)
      if (ESMF_LogFoundError(localrc, &
        ESMF_ERR_PASSTHRU, &
        ESMF_CONTEXT, rcToReturn=rc)) return
    else
      ! call Comp method
      call ESMF_CompSet(gridcomp%compp, name=name, &
        grid=grid, gridList=gridList, mesh=mesh, meshList=meshList, &
        locstream=locstream, locstreamList=locstreamList, xgrid=xgrid, &
        xgridList=xgridList, clock=clock, configFile=configFile, config=config, &
        rc=localrc)
      if (ESMF_LogFoundError(localrc, &
        ESMF_ERR_PASSTHRU, &
        ESMF_CONTEXT, rcToReturn=rc)) return
    endif

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS
  end subroutine ESMF_GridCompSet
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompSetEntryPoint"
!BOP
! !IROUTINE: ESMF_GridCompSetEntryPoint - Set user routine as entry point for standard GridComp method
!
! !INTERFACE:
  recursive subroutine ESMF_GridCompSetEntryPoint(gridcomp, methodflag, &
    userRoutine, keywordEnforcer, phase, rc)

! !ARGUMENTS:
    type(ESMF_GridComp),    intent(inout)         :: gridcomp
    type(ESMF_Method_Flag), intent(in)            :: methodflag
    interface
      subroutine userRoutine(gridcomp, importState, exportState, clock, rc)
        use ESMF_CompMod
        use ESMF_StateMod
        use ESMF_ClockMod
        implicit none
        type(ESMF_GridComp)         :: gridcomp     ! must not be optional
        type(ESMF_State)            :: importState  ! must not be optional
        type(ESMF_State)            :: exportState  ! must not be optional
        type(ESMF_Clock)            :: clock        ! must not be optional
        integer, intent(out)        :: rc           ! must not be optional
      end subroutine
    end interface
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    integer,                intent(in),  optional :: phase
    integer,                intent(out), optional :: rc
!
! !STATUS:
! \begin{itemize}
! \item\apiStatusCompatibleVersion{5.2.0r}
! \end{itemize}
!
! !DESCRIPTION:
! Registers a user-supplied {\tt userRoutine} as the entry point for one of the
! predefined Component {\tt methodflag}s. After this call the {\tt userRoutine}
! becomes accessible via the standard Component method API.
!
! The arguments are:
! \begin{description}
! \item[gridcomp]
!   An {\tt ESMF\_GridComp} object.
! \item[methodflag]
!   \begin{sloppypar}
!   One of a set of predefined Component methods - e.g.
!   {\tt ESMF\_METHOD\_INITIALIZE}, {\tt ESMF\_METHOD\_RUN},
!   {\tt ESMF\_METHOD\_FINALIZE}. See section \ref{const:method}
!   for a complete list of valid method options.
!   \end{sloppypar}
! \item[userRoutine]
!   The user-supplied subroutine to be associated for this Component
!   {\tt method}.  Argument types, intent and order must match
!   the interface signature, and must not have the {\tt optional} attribute.
!   Prior to Fortran-2008, the subroutine must be either a module scope procedure,
!   or an external procedure that has a matching interface block specified for it.
!   An internal procedure which is contained within another procedure must not be used.
!   From Fortran-2008 onwards, an internal procedure contained within either a main program
!   or a module procedure may be used.  If the internal procedure is contained within a
!   module procedure, it is subject to initialization requirements.  See: \ref{sec:AppDriverIntProc}
! \item[{[phase]}]
!   The {\tt phase} number for multi-phase methods. For single phase
!   methods the {\tt phase} argument can be omitted. The default setting
!   is 1.
! \item[{[rc]}]
!   Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOP
!------------------------------------------------------------------------------
    integer :: localrc                       ! local error status
    integer :: phaseArg

    ! initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit, gridcomp, rc)

    phaseArg = 1   ! default
    if (present(phase)) phaseArg = phase

    call c_ESMC_SetEntryPoint(gridcomp, methodflag, userRoutine, phaseArg, &
      localrc)
!TODO: back in once thread-safe    if (ESMF_LogFoundError(localrc, &
!TODO: back in once thread-safe      ESMF_ERR_PASSTHRU, &
!TODO: back in once thread-safe      ESMF_CONTEXT, rcToReturn=rc)) return

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS
  end subroutine ESMF_GridCompSetEntryPoint
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
!BOP
! !IROUTINE: ESMF_GridCompSetInternalState - Set private data block pointer
!
! !INTERFACE:
! subroutine ESMF_GridCompSetInternalState(gridcomp, wrappedDataPointer, rc)
!
! !ARGUMENTS:
!   type(ESMF_GridComp)             :: gridcomp
!   type(wrapper)                   :: wrappedDataPointer
!   integer,            intent(out) :: rc
!
! !STATUS:
! \begin{itemize}
! \item\apiStatusCompatibleVersion{5.2.0r}
! \end{itemize}
!
! !DESCRIPTION:
! Available to be called by an {\tt ESMF\_GridComp} at any time, but
! expected to be
! most useful when called during the registration process, or initialization.
! Since init, run, and finalize must be separate subroutines, data that
! they need to share in common can either be module global data, or can
! be allocated in a private data block and the address of that block
! can be registered with the framework and retrieved by subsequent calls.
! When running multiple instantiations of an {\tt ESMF\_GridComp},
! for example during
! ensemble runs, it may be simpler to maintain private data specific to
! each run with private data blocks.  A corresponding
! {\tt ESMF\_GridCompGetInternalState} call retrieves the data pointer.
!
! Only the {\em last} data block set via
! {\tt ESMF\_GridCompSetInternalState} will be accessible.
!
! CAUTION: If you are working with a compiler that does not support Fortran 2018
! assumed-type dummy arguments, then this method does not have an explicit
! Fortran interface. In this case do not specify argument keywords when calling
! this method!
!
! The arguments are:
! \begin{description}
! \item[gridcomp]
!   An {\tt ESMF\_GridComp} object.
! \item[wrappedDataPointer]
!   A pointer to the private data block, wrapped in a derived type which
!   contains only a pointer to the block.  This level of indirection is
!   needed to reliably set and retrieve the data block no matter which
!   architecture or compiler is used.
! \item[rc]
!   Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
!   Note: unlike most other ESMF routines, this argument is not optional
!   because of implementation considerations.
! \end{description}
!
!EOP
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompSetServices"
!BOP
! !IROUTINE: ESMF_GridCompSetServices - Call user routine to register GridComp methods
!
! !INTERFACE:
  recursive subroutine ESMF_GridCompSetServices(gridcomp, &
    userRoutine, keywordEnforcer, userRc, rc)
!
! !ARGUMENTS:
    type(ESMF_GridComp), intent(inout)         :: gridcomp
    interface
      subroutine userRoutine(gridcomp, rc)
        use ESMF_CompMod
        implicit none
        type(ESMF_GridComp)        :: gridcomp ! must not be optional
        integer, intent(out)       :: rc       ! must not be optional
      end subroutine
    end interface
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    integer,             intent(out), optional :: userRc
    integer,             intent(out), optional :: rc
!
! !STATUS:
! \begin{itemize}
! \item\apiStatusCompatibleVersion{5.2.0r}
! \end{itemize}
!
! !DESCRIPTION:
! \label{GridComp:SetServices}
! Call into user provided {\tt userRoutine} which is responsible for
! setting Component's Initialize(), Run(), and Finalize() services.
!
! The arguments are:
! \begin{description}
! \item[gridcomp]
!   Gridded Component.
! \item[userRoutine]
!   The Component writer must supply a subroutine with the exact interface
!   shown above for the {\tt userRoutine} argument. Arguments in {\tt userRoutine}
!   must not be declared as optional, and the types, intent and order must match.
!   Prior to Fortran-2008, the subroutine must be either a module scope procedure,
!   or an external procedure that has a matching interface block specified for it.
!   An internal procedure which is contained within another procedure must not be used.
!   From Fortran-2008 onwards, an internal procedure contained within either a main program
!   or a module procedure may be used.  If the internal procedure is contained within a
!   module procedure, it is subject to initialization requirements.  See: \ref{sec:AppDriverIntProc}
!
!   \begin{sloppypar}
!   The {\tt userRoutine}, when called by the framework, must make successive calls
!   to {\tt ESMF\_GridCompSetEntryPoint()} to preset callback routines for
!   standard Component Initialize(), Run(), and Finalize() methods.
!   \end{sloppypar}
! \item[{[userRc]}]
!   Return code set by {\tt userRoutine} before returning.
! \item[{[rc]}]
!   Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!
!EOP
!------------------------------------------------------------------------------
    integer :: localrc                       ! local error status
    integer :: localUserRc

    ! initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit, gridcomp, rc)

    call c_ESMC_SetServices(gridcomp, userRoutine, localUserRc, localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! now indicate that this Component has a VM associated
    gridcomp%compp%compStatus%vmIsPresent = .true.

    ! pass back userRc
    if (present(userRc)) userRc = localUserRc

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS
  end subroutine ESMF_GridCompSetServices
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompSetServicesShObj"
!BOP
! !IROUTINE: ESMF_GridCompSetServices - Call user routine through name lookup, to register GridComp methods
!
! !INTERFACE:
  ! Private name; call using ESMF_GridCompSetServices()
  recursive subroutine ESMF_GridCompSetServicesShObj(gridcomp, userRoutine, &
    keywordEnforcer, sharedObj, userRoutineFound, userRc, rc)
!
! !ARGUMENTS:
    type(ESMF_GridComp), intent(inout)         :: gridcomp
    character(len=*),    intent(in)            :: userRoutine
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    character(len=*),    intent(in),  optional :: sharedObj
    logical,             intent(out), optional :: userRoutineFound
    integer,             intent(out), optional :: userRc
    integer,             intent(out), optional :: rc
!
! !STATUS:
! \begin{itemize}
! \item\apiStatusCompatibleVersion{5.2.0r}
! \item\apiStatusModifiedSinceVersion{5.2.0r}
! \begin{description}
! \item[6.3.0r] Added argument {\tt userRoutineFound}.
!              The new argument provides a way to test availability without
!              causing error conditions.
! \end{description}
! \end{itemize}
!
! !DESCRIPTION:
! \label{GridComp:SetServicesShObj}
! Call into a user provided routine which is responsible for setting
! Component's Initialize(), Run(), and Finalize() services. The named
! {\tt userRoutine} must exist in the executable, or in the shared object
! specified by {\tt sharedObj}. In the latter case all of the platform
! specific details about dynamic linking and loading apply.
!
! The arguments are:
! \begin{description}
! \item[gridcomp]
!   Gridded Component.
! \item[userRoutine]
!   Name of routine to be called, specified as a character string.
!   The Component writer must supply a subroutine with the exact interface
!   shown for {\tt userRoutine} below. Arguments must not be declared
!   as optional, and the types, intent and order must match.
!   Prior to Fortran-2008, the subroutine must be either a module scope procedure,
!   or an external procedure that has a matching interface block specified for it.
!   An internal procedure which is contained within another procedure must not be used.
!   From Fortran-2008 onwards, an internal procedure contained within either a main program
!   or a module procedure may be used.  If the internal procedure is contained within a
!   module procedure, it is subject to initialization requirements.  See: \ref{sec:AppDriverIntProc}
!
!   !INTERFACE:
!     interface
!       subroutine userRoutine(gridcomp, rc)
!         type(ESMF_GridComp)  :: gridcomp   ! must not be optional
!         integer, intent(out) :: rc         ! must not be optional
!       end subroutine
!     end interface
!
!   !DESCRIPTION:
!   \begin{sloppypar}
!   The {\tt userRoutine}, when called by the framework, must make successive calls
!   to {\tt ESMF\_GridCompSetEntryPoint()} to preset callback routines for
!   standard Component Initialize(), Run(), and Finalize() methods.
!   \end{sloppypar}
! \item[{[sharedObj]}]
!   Name of shared object that contains {\tt userRoutine}. If the
!   {\tt sharedObj} argument is not provided the executable itself will be
!   searched for {\tt userRoutine}.
! \item[{[userRoutineFound]}]
!   Report back whether the specified {\tt userRoutine} was found and executed,
!   or was not available. If this argument is present, not finding the
!   {\tt userRoutine} will not result in returning an error in {\tt rc}.
!   The default is to return an error if the {\tt userRoutine} cannot be found.
! \item[{[userRc]}]
!   Return code set by {\tt userRoutine} before returning.
! \item[{[rc]}]
!   Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOP
!------------------------------------------------------------------------------
    integer :: localrc                       ! local error status
    integer :: localUserRc
    character(len=0)    :: emptyString
    type(ESMF_Logical)  :: userRoutineFoundHelp
    logical             :: userRoutineFoundHelpHelp

    ! initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit, gridcomp, rc)

    if (present(sharedObj)) then
      call c_ESMC_SetServicesShObj(gridcomp, userRoutine, sharedObj, &
        userRoutineFoundHelp, localUserRc, localrc)
    else
      call c_ESMC_SetServicesShObj(gridcomp, userRoutine, emptyString, &
        userRoutineFoundHelp, localUserRc, localrc)
    endif
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! translate ESMF_Logical -> logical
    userRoutineFoundHelpHelp = userRoutineFoundHelp

    ! report back
    if (present(userRoutineFound)) userRoutineFound = userRoutineFoundHelpHelp

    if (userRoutineFoundHelpHelp) then
      ! routine found and executed -> indicate this Component has VM associated
      gridcomp%compp%compStatus%vmIsPresent = .true.
    else
      ! routine not found
      if (.not.present(userRoutineFound)) then
        ! an error condition that needs to be reported back
        call ESMF_LogSetError(ESMF_RC_ARG_BAD, &
          msg="userRoutine was not found", &
          ESMF_CONTEXT, rcToReturn=rc)
        return
      endif
    endif

    ! pass back userRc
    if (present(userRc)) userRc = localUserRc

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS
  end subroutine ESMF_GridCompSetServicesShObj
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompSetServicesComp"
!BOP
! !IROUTINE: ESMF_GridCompSetServices - Set to serve as Dual Component for an Actual Component
!
! !INTERFACE:
  ! Private name; call using ESMF_GridCompSetServices()
  recursive subroutine ESMF_GridCompSetServicesComp(gridcomp, &
    actualGridcomp, keywordEnforcer, rc)
!
! !ARGUMENTS:
    type(ESMF_GridComp), intent(inout)         :: gridcomp
    type(ESMF_GridComp), intent(in)            :: actualGridcomp
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    integer,             intent(out), optional :: rc
!
! !DESCRIPTION:
! Set the services of a Gridded Component to serve a "dual" Component for an
! "actual" Component. The component tunnel is VM based.
!
! The arguments are:
! \begin{description}
! \item[gridcomp]
!   Dual Gridded Component.
! \item[actualGridcomp]
!   Actual Gridded Component.
! \item[{[rc]}]
!   Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOP
!------------------------------------------------------------------------------
    integer :: localrc                        ! local error status
    integer, pointer :: actualCompPetList(:)
    integer :: actualCompRootPet, i

    ! initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit, gridcomp, rc)
    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit, actualGridcomp, rc)

    ! access the petList of the actualGridcomp and find the lowest PET
    ! -> this is going to be the rendezvous PET for the component tunnel setup
    nullify(actualCompPetList)
    ! call Comp method
    call ESMF_CompGet(actualGridcomp%compp, petList=actualCompPetList, &
      rc=localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return
    actualCompRootPet = actualCompPetList(1)  ! prime the search variable
    do i=2, size(actualCompPetList)
      if (actualCompPetList(i) < actualCompRootPet) &
        actualCompRootPet = actualCompPetList(i)
    enddo
    deallocate(actualCompPetList)

    call c_ESMC_SetServicesComp(gridcomp, gridcomp%compp%compTunnel, &
      actualGridcomp, actualCompRootPet, localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! now indicate that this Component has a VM associated
    gridcomp%compp%compStatus%vmIsPresent = .true.

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS
  end subroutine ESMF_GridCompSetServicesComp
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompSetServicesSock"
!BOP
! !IROUTINE: ESMF_GridCompSetServices - Set to serve as Dual Component for an Actual Component through sockets
!
! !INTERFACE:
  ! Private name; call using ESMF_GridCompSetServices()
  recursive subroutine ESMF_GridCompSetServicesSock(gridcomp, port, &
    keywordEnforcer, server, timeout, timeoutFlag, rc)
!
! !ARGUMENTS:
    type(ESMF_GridComp), intent(inout)         :: gridcomp
    integer,             intent(in)            :: port
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    character(len=*),    intent(in),  optional :: server
    integer,             intent(in),  optional :: timeout
    logical,             intent(out), optional :: timeoutFlag
    integer,             intent(out), optional :: rc
!
! !DESCRIPTION:
! Set the services of a Gridded Component to serve a "dual" Component for an
! "actual" Component. The component tunnel is socket based.
!
! The arguments are:
! \begin{description}
! \item[gridcomp]
!   Dual Gridded Component.
! \item[port]
!   Port number under which the actual component is being served. The valid
!   port range is [1024, 65535].
! \item[{[server]}]
!   Server name where the actual component is being served. The default, i.e.
!   if the {\tt server} argument was not provided, is {\tt localhost}.
! \item[{[timeout]}]
!   The maximum period in seconds that this call will wait in communications
!   with the actual component, before returning with a timeout condition.
!   The default is 3600, i.e. 1 hour.
! \item[{[timeoutFlag]}]
!   Returns {\tt .true.} if the timeout was reached, {\tt .false.} otherwise.
!   If {\tt timeoutFlag} was {\em not} provided, a timeout condition will lead
!   to a return code of {\tt rc \textbackslash = ESMF\_SUCCESS}. Otherwise the
!   return value of {\tt timeoutFlag} is the sole indicator of a timeout
!   condition.
! \item[{[rc]}]
!   Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOP
!------------------------------------------------------------------------------
    integer :: localrc                        ! local error status
    integer :: timeoutArg

    ! initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit, gridcomp, rc)

    timeoutArg = ESMF_DEFAULT_TIMEOUT ! default 1h
    if (present(timeout)) timeoutArg = timeout

    if (present(server)) then
      call c_ESMC_SetServicesSock(gridcomp, gridcomp%compp%compTunnel, &
        port, server, timeoutArg, localrc)
    else
      call c_ESMC_SetServicesSock(gridcomp, gridcomp%compp%compTunnel, &
        port, "localhost", timeoutArg, localrc)
    endif
    ! conditionally filter out the RC_TIMEOUT and return success
    if (present(timeoutFlag)) then
      timeoutFlag = .false. ! initialize
      if ((localrc==ESMF_RC_TIMEOUT).or.(localrc==ESMC_RC_TIMEOUT)) then
        timeoutFlag = .true.      ! indicate timeout through flag argument
        localrc = ESMF_SUCCESS    ! do not raise error condition on user level
      endif
    endif
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! now indicate that this Component has a VM associated
    gridcomp%compp%compStatus%vmIsPresent = .true.

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS
  end subroutine ESMF_GridCompSetServicesSock
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompSetVM"
!BOP
! !IROUTINE: ESMF_GridCompSetVM - Call user routine to set GridComp VM properties
!
! !INTERFACE:
  recursive subroutine ESMF_GridCompSetVM(gridcomp, userRoutine, keywordEnforcer, &
    userRc, rc)
! !ARGUMENTS:
    type(ESMF_GridComp), intent(inout)         :: gridcomp
    interface
      subroutine userRoutine(gridcomp, rc)
        use ESMF_CompMod
        implicit none
        type(ESMF_GridComp)        :: gridcomp ! must not be optional
        integer, intent(out)       :: rc       ! must not be optional
      end subroutine
    end interface
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    integer,             intent(out), optional :: userRc
    integer,             intent(out), optional :: rc
!
! !STATUS:
! \begin{itemize}
! \item\apiStatusCompatibleVersion{5.2.0r}
! \end{itemize}
!
! !DESCRIPTION:
! Optionally call into user provided {\tt userRoutine} which is responsible
! for setting Component's VM properties.
!
! The arguments are:
! \begin{description}
! \item[gridcomp]
!   Gridded Component.
! \item[userRoutine]
!   The Component writer must supply a subroutine with the exact interface
!   shown above for the {\tt userRoutine} argument. Arguments in {\tt userRoutine}
!   must not be declared as optional, and the types, intent and order must match.
!   Prior to Fortran-2008, the subroutine must be either a module scope procedure,
!   or an external procedure that has a matching interface block specified for it.
!   An internal procedure which is contained within another procedure must not be used.
!   From Fortran-2008 onwards, an internal procedure contained within either a main program
!   or a module procedure may be used.  If the internal procedure is contained within a
!   module procedure, it is subject to initialization requirements.  See: \ref{sec:AppDriverIntProc}
!
!   The subroutine, when called by the framework, is expected to use any of the
!   {\tt ESMF\_GridCompSetVMxxx()} methods to set the properties of the VM
!   associated with the Gridded Component.
! \item[{[userRc]}]
!   Return code set by {\tt userRoutine} before returning.
! \item[{[rc]}]
!   Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOP
!------------------------------------------------------------------------------
    integer :: localrc                       ! local error status
    integer :: localUserRc

    ! initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit, gridcomp, rc)

    call c_ESMC_SetVM(gridcomp, userRoutine, localUserRc, localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! pass back userRc
    if (present(userRc)) userRc = localUserRc

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS
  end subroutine ESMF_GridCompSetVM
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompSetVMShObj"
!BOP
! !IROUTINE: ESMF_GridCompSetVM - Call user routine through name lookup, to set GridComp VM properties
!
! !INTERFACE:
  ! Private name; call using ESMF_GridCompSetVM()
  recursive subroutine ESMF_GridCompSetVMShObj(gridcomp, userRoutine, &
    keywordEnforcer, sharedObj, userRoutineFound, userRc, rc)
!
! !ARGUMENTS:
    type(ESMF_GridComp), intent(inout)         :: gridcomp
    character(len=*),    intent(in)            :: userRoutine
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    character(len=*),    intent(in),  optional :: sharedObj
    logical,             intent(out), optional :: userRoutineFound
    integer,             intent(out), optional :: userRc
    integer,             intent(out), optional :: rc
!
! !STATUS:
! \begin{itemize}
! \item\apiStatusCompatibleVersion{5.2.0r}
! \item\apiStatusModifiedSinceVersion{5.2.0r}
! \begin{description}
! \item[8.4.0] Added argument {\tt userRoutineFound}.
!              The new argument provides a way to test availability without
!              causing error conditions.
! \end{description}
! \end{itemize}
!
! !DESCRIPTION:
! Optionally call into user provided {\tt userRoutine} which is responsible
! for setting Component's VM properties. The named
! {\tt userRoutine} must exist in the executable, or in the shared object
! specified by {\tt sharedObj}. In the latter case all of the platform
! specific details about dynamic linking and loading apply.
!
! The arguments are:
! \begin{description}
! \item[gridcomp]
!   Gridded Component.
! \item[userRoutine]
!   Routine to be called, specified as a character string.
!   The Component writer must supply a subroutine with the exact interface
!   shown for {\tt userRoutine} below. Arguments must not be declared
!   as optional, and the types, intent and order must match.
!   Prior to Fortran-2008, the subroutine must be either a module scope procedure,
!   or an external procedure that has a matching interface block specified for it.
!   An internal procedure which is contained within another procedure must not be used.
!   From Fortran-2008 onwards, an internal procedure contained within either a main program
!   or a module procedure may be used.  If the internal procedure is contained within a
!   module procedure, it is subject to initialization requirements.  See: \ref{sec:AppDriverIntProc}
!
!   !INTERFACE:
!     interface
!       subroutine userRoutine(gridcomp, rc)
!         type(ESMF_GridComp)  :: gridcomp    ! must not be optional
!         integer, intent(out) :: rc          ! must not be optional
!       end subroutine
!     end interface
!
!   !DESCRIPTION:
!   The subroutine, when called by the framework, is expected to use any of the
!   {\tt ESMF\_GridCompSetVMxxx()} methods to set the properties of the VM
!   associated with the Gridded Component.
! \item[{[sharedObj]}]
!   Name of shared object that contains {\tt userRoutine}. If the
!   {\tt sharedObj} argument is not provided the executable itself will be
!   searched for {\tt userRoutine}.
! \item[{[userRoutineFound]}]
!   Report back whether the specified {\tt userRoutine} was found and executed,
!   or was not available. If this argument is present, not finding the
!   {\tt userRoutine} will not result in returning an error in {\tt rc}.
!   The default is to return an error if the {\tt userRoutine} cannot be found.
! \item[{[userRc]}]
!   Return code set by {\tt userRoutine} before returning.
! \item[{[rc]}]
!   Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOP
!------------------------------------------------------------------------------
    integer :: localrc                       ! local error status
    integer :: localUserRc
    character(len=0) :: emptyString
    type(ESMF_Logical)  :: userRoutineFoundHelp
    logical             :: userRoutineFoundHelpHelp

    ! initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit, gridcomp, rc)

    if (present(sharedObj)) then
      call c_ESMC_SetVMShObj(gridcomp, userRoutine, sharedObj, &
        userRoutineFoundHelp, localUserRc, localrc)
    else
      call c_ESMC_SetVMShObj(gridcomp, userRoutine, emptyString, &
        userRoutineFoundHelp, localUserRc, localrc)
    endif
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! translate ESMF_Logical -> logical
    userRoutineFoundHelpHelp = userRoutineFoundHelp

    ! report back
    if (present(userRoutineFound)) userRoutineFound = userRoutineFoundHelpHelp

    ! pass back userRc
    if (present(userRc)) userRc = localUserRc

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS
  end subroutine ESMF_GridCompSetVMShObj
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompSetVMMaxPEs"
!BOP
! !IROUTINE: ESMF_GridCompSetVMMaxPEs - Associate PEs with PETs in GridComp VM
!
! !INTERFACE:
  subroutine ESMF_GridCompSetVMMaxPEs(gridcomp, keywordEnforcer, &
    maxPeCountPerPet, prefIntraProcess, prefIntraSsi, prefInterSsi, &
    pthreadMinStackSize, openMpHandling, openMpNumThreads, &
    forceChildPthreads, rc)
!
! !ARGUMENTS:
    type(ESMF_GridComp), intent(inout)         :: gridcomp
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    integer,             intent(in),  optional :: maxPeCountPerPet
    integer,             intent(in),  optional :: prefIntraProcess
    integer,             intent(in),  optional :: prefIntraSsi
    integer,             intent(in),  optional :: prefInterSsi
    integer,             intent(in),  optional :: pthreadMinStackSize
    character(*),        intent(in),  optional :: openMpHandling
    integer,             intent(in),  optional :: openMpNumThreads
    logical,             intent(in),  optional :: forceChildPthreads
    integer,             intent(out), optional :: rc
!
! !DESCRIPTION:
!   Set characteristics of the {\tt ESMF\_VM} for this {\tt ESMF\_GridComp}.
!   Attempts to associate up to {\tt maxPeCountPerPet} PEs with each PET. Only
!   PEs that are located on the same single system image (SSI) can be associated
!   with the same PET. Within this constraint the call tries to get as close as
!   possible to the number specified by {\tt maxPeCountPerPet}.
!
!   The other constraint to this call is that the number of PEs is preserved.
!   This means that the child Component in the end is associated with as many
!   PEs as the parent Component provided to the child. The number of child PETs
!   however is adjusted according to the above rule.
!
!   The typical use of {\tt ESMF\_GridCompSetVMMaxPEs()} is to allocate
!   multiple PEs per PET in a Component for user-level threading, e.g. OpenMP.
!
! The arguments are:
! \begin{description}
! \item[gridcomp]
!   {\tt ESMF\_GridComp} to set the {\tt ESMF\_VM} for.
! \item[{[maxPeCountPerPet]}]
!   Maximum number of PEs on each PET.
!   Default for each SSI is the local number of PEs.
! \item[{[prefIntraProcess]}]
!   Communication preference within a single process.
!   {\em Currently options not documented. Use default.}
! \item[{[prefIntraSsi]}]
!   Communication preference within a single system image (SSI).
!   {\em Currently options not documented. Use default.}
! \item[{[prefInterSsi]}]
!   Communication preference between different single system images (SSIs).
!   {\em Currently options not documented. Use default.}
! \item[{[pthreadMinStackSize]}]
!   Minimum stack size in byte of any child PET executing as Pthread. By default
!   single threaded child PETs do {\em not} execute as Pthread, and their stack
!   size is unaffected by this argument. However, for multi-threaded child PETs,
!   or if {\tt forceChildPthreads} is {\tt .true.}, child PETs execute
!   as Pthreads with their own private stack.
!
!   For cases where OpenMP threads
!   are used by the user code, each thread allocates its own private stack. For
!   all threads {\em other} than the master, the stack size is set via the 
!   typical {\tt OMP\_STACKSIZE} environment variable mechanism. The PET itself,
!   however, becomes the {\em master} of the OpenMP thread team, and is not
!   affected by {\tt OMP\_STACKSIZE}. It is the master's stack that can be
!   sized via the {\tt pthreadMinStackSize} argument, and a large enough size
!   is often critical.
!
!   When {\tt pthreadMinStackSize}
!   is absent, the default is to use the system default
!   set by the {\tt limit} or {\tt ulimit} command. However, the stack of a
!   Pthread cannot be unlimited, and a shell {\em stacksize} setting of
!   {\em unlimited}, or any setting below the ESMF implemented minimum,
!   will result in setting the stack size to 20MiB (the ESMF minimum).
!   Depending on how much private data is used by the user code under
!   the master thread, the default might be too small, and
!   {\tt pthreadMinStackSize} must be used to allocate sufficient stack space.
! \item[{[openMpHandling]}] 
!   Handling of OpenMP threads. Supported options are:
!   \begin{itemize}
!   \item "{\tt none}" - OpenMP handling is completely left to the user.
!   \item "{\tt set}"  - ESMF uses the {\tt omp\_set\_num\_threads()} API to set
!                        the number of OpenMP threads in each team.
!   \item "{\tt init}" - ESMF sets the number of OpenMP threads in each team,
!                        and triggers the instantiation of the team.
!   \item "{\tt pin}" (default) - ESMF sets the number of OpenMP threads in each team,
!                        triggers the instantiation of the team, and pins each
!                        OpenMP thread to the corresponding PE.
!   \end{itemize}
! \item[{[openMpNumThreads]}] 
!   Number of OpenMP threads in each OpenMP thread team. This can be any
!   positive number. By default, or if {\tt openMpNumThreads} is negative, each
!   PET sets the number of OpenMP threads to its local peCount.
! \item[{[forceChildPthreads]}] 
!   For {\tt .true.}, force each child PET to execute in its own Pthread.
!   By default, {\tt .false.}, single PETs spawned from a parent PET
!   execute in the same thread (or MPI process) as the parent PET. Multiple
!   child PETs spawned by the same parent PET always execute as their own
!   Pthreads.
! \item[{[rc]}]
!   Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOP
!------------------------------------------------------------------------------
    integer :: localrc                     ! local error status

    ! initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit,gridcomp,rc)

    ! call Comp method
    call ESMF_CompSetVMMaxPEs(gridcomp%compp, maxPeCountPerPet, &
      prefIntraProcess, prefIntraSsi, prefInterSsi, pthreadMinStackSize, &
      openMpHandling, openMpNumThreads, forceChildPthreads, rc=localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS
  end subroutine ESMF_GridCompSetVMMaxPEs
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompSetVMMaxThreads"
!BOP
! !IROUTINE: ESMF_GridCompSetVMMaxThreads - Set multi-threaded PETs in GridComp VM
!
! !INTERFACE:
  subroutine ESMF_GridCompSetVMMaxThreads(gridcomp, keywordEnforcer, &
    maxPetCountPerVas, prefIntraProcess, prefIntraSsi, prefInterSsi, &
    pthreadMinStackSize, forceChildPthreads, rc)
!
! !ARGUMENTS:
    type(ESMF_GridComp), intent(inout)         :: gridcomp
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    integer,             intent(in),  optional :: maxPetCountPerVas
    integer,             intent(in),  optional :: prefIntraProcess
    integer,             intent(in),  optional :: prefIntraSsi
    integer,             intent(in),  optional :: prefInterSsi
    integer,             intent(in),  optional :: pthreadMinStackSize
    logical,             intent(in),  optional :: forceChildPthreads
    integer,             intent(out), optional :: rc
!
! !DESCRIPTION:
!   Set characteristics of the {\tt ESMF\_VM} for this {\tt ESMF\_GridComp}.
!   Attempts to provide {\tt maxPetCountPerVas} threaded PETs in each
!   virtual address space (VAS). Only as many threaded PETs as there are PEs
!   located on the single system image (SSI) can be associated with the VAS.
!   Within this constraint the call tries to get as close as possible to the
!   number specified by {\tt maxPetCountPerVas}.
!
!   The other constraint to this call is that the number of PETs is preserved.
!   This means that the child Component in the end is associated with as many
!   PETs as the parent Component provided to the child. The threading level of
!   the child PETs however is adjusted according to the above rule.
!
!   The typical use of {\tt ESMF\_GridCompSetVMMaxThreads()} is to run a
!   Component multi-threaded with groups of PETs executing within a common
!   virtual address space.
!
! The arguments are:
! \begin{description}
! \item[gridcomp]
!   {\tt ESMF\_GridComp} to set the {\tt ESMF\_VM} for.
! \item[{[maxPetCountPerVas]}]
!   Maximum number of threaded PETs in each virtual address space (VAS).
!   Default for each SSI is the local number of PEs.
! \item[{[prefIntraProcess]}]
!   Communication preference within a single process.
!   {\em Currently options not documented. Use default.}
! \item[{[prefIntraSsi]}]
!   Communication preference within a single system image (SSI).
!   {\em Currently options not documented. Use default.}
! \item[{[prefInterSsi]}]
!   Communication preference between different single system images (SSIs).
!   {\em Currently options not documented. Use default.}
! \item[{[pthreadMinStackSize]}]
!   Minimum stack size in byte of any child PET executing as Pthread. By default
!   single threaded child PETs do {\em not} execute as Pthread, and their stack
!   size is unaffected by this argument. However, for multi-threaded child PETs,
!   or if {\tt forceChildPthreads} is {\tt .true.}, child PETs execute
!   as Pthreads with their own private stack.
!
!   For cases where OpenMP threads
!   are used by the user code, each thread allocates its own private stack. For
!   all threads {\em other} than the master, the stack size is set via the 
!   typical {\tt OMP\_STACKSIZE} environment variable mechanism. The PET itself,
!   however, becomes the {\em master} of the OpenMP thread team, and is not
!   affected by {\tt OMP\_STACKSIZE}. It is the master's stack that can be
!   sized via the {\tt pthreadMinStackSize} argument, and a large enough size
!   is often critical.
!
!   When {\tt pthreadMinStackSize}
!   is absent, the default is to use the system default
!   set by the {\tt limit} or {\tt ulimit} command. However, the stack of a
!   Pthread cannot be unlimited, and a shell {\em stacksize} setting of
!   {\em unlimited}, or any setting below the ESMF implemented minimum,
!   will result in setting the stack size to 20MiB (the ESMF minimum).
!   Depending on how much private data is used by the user code under
!   the master thread, the default might be too small, and
!   {\tt pthreadMinStackSize} must be used to allocate sufficient stack space.
! \item[{[forceChildPthreads]}] 
!   For {\tt .true.}, force each child PET to execute in its own Pthread.
!   By default, {\tt .false.}, single PETs spawned from a parent PET
!   execute in the same thread (or MPI process) as the parent PET. Multiple
!   child PETs spawned by the same parent PET always execute as their own
!   Pthreads.
! \item[{[rc]}]
!   Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOP
!------------------------------------------------------------------------------
    integer :: localrc                     ! local error status

    ! initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit,gridcomp,rc)

    ! call Comp method
    call ESMF_CompSetVMMaxThreads(gridcomp%compp, maxPetCountPerVas, &
      prefIntraProcess, prefIntraSsi, prefInterSsi, pthreadMinStackSize, &
      forceChildPthreads, rc=localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS
  end subroutine ESMF_GridCompSetVMMaxThreads
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompSetVMMinThreads"
!BOP
! !IROUTINE: ESMF_GridCompSetVMMinThreads - Set a reduced threading level in GridComp VM
!
! !INTERFACE:
  subroutine ESMF_GridCompSetVMMinThreads(gridcomp, keywordEnforcer, &
    maxPeCountPerPet, prefIntraProcess, prefIntraSsi, prefInterSsi, &
    pthreadMinStackSize, forceChildPthreads, rc)
!
! !ARGUMENTS:
    type(ESMF_GridComp), intent(inout)         :: gridcomp
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    integer,             intent(in),  optional :: maxPeCountPerPet
    integer,             intent(in),  optional :: prefIntraProcess
    integer,             intent(in),  optional :: prefIntraSsi
    integer,             intent(in),  optional :: prefInterSsi
    integer,             intent(in),  optional :: pthreadMinStackSize
    logical,             intent(in),  optional :: forceChildPthreads
    integer,             intent(out), optional :: rc
!
! !DESCRIPTION:
!   Set characteristics of the {\tt ESMF\_VM} for this {\tt ESMF\_GridComp}.
!   Reduces the number of threaded PETs in each VAS. The {\tt max} argument
!   may be specified to limit the maximum number of PEs that a single PET
!   can be associated with.
!
!   Several constraints apply: 1) the number of PEs cannot change, 2) PEs
!   cannot migrate between single system images (SSIs), 3) the number of PETs
!   cannot increase, only decrease, 4) PETs cannot migrate between virtual
!   address spaces (VASs), nor can VASs migrate between SSIs.
!
!   The typical use of {\tt ESMF\_GridCompSetVMMinThreads()} is to run a
!   Component across a set of single-threaded PETs.
!
! The arguments are:
! \begin{description}
! \item[gridcomp]
!   {\tt ESMF\_GridComp} to set the {\tt ESMF\_VM} for.
! \item[{[maxPeCountPerPet]}]
!   Maximum number of PEs on each PET.
!   Default for each SSI is the local number of PEs.
! \item[{[prefIntraProcess]}]
!   Communication preference within a single process.
!   {\em Currently options not documented. Use default.}
! \item[{[prefIntraSsi]}]
!   Communication preference within a single system image (SSI).
!   {\em Currently options not documented. Use default.}
! \item[{[prefInterSsi]}]
!   Communication preference between different single system images (SSIs).
!   {\em Currently options not documented. Use default.}
! \item[{[pthreadMinStackSize]}]
!   Minimum stack size in byte of any child PET executing as Pthread. By default
!   single threaded child PETs do {\em not} execute as Pthread, and their stack
!   size is unaffected by this argument. However, for multi-threaded child PETs,
!   or if {\tt forceChildPthreads} is {\tt .true.}, child PETs execute
!   as Pthreads with their own private stack.
!
!   For cases where OpenMP threads
!   are used by the user code, each thread allocates its own private stack. For
!   all threads {\em other} than the master, the stack size is set via the 
!   typical {\tt OMP\_STACKSIZE} environment variable mechanism. The PET itself,
!   however, becomes the {\em master} of the OpenMP thread team, and is not
!   affected by {\tt OMP\_STACKSIZE}. It is the master's stack that can be
!   sized via the {\tt pthreadMinStackSize} argument, and a large enough size
!   is often critical.
!
!   When {\tt pthreadMinStackSize}
!   is absent, the default is to use the system default
!   set by the {\tt limit} or {\tt ulimit} command. However, the stack of a
!   Pthread cannot be unlimited, and a shell {\em stacksize} setting of
!   {\em unlimited}, or any setting below the ESMF implemented minimum,
!   will result in setting the stack size to 20MiB (the ESMF minimum).
!   Depending on how much private data is used by the user code under
!   the master thread, the default might be too small, and
!   {\tt pthreadMinStackSize} must be used to allocate sufficient stack space.
! \item[{[forceChildPthreads]}] 
!   For {\tt .true.}, force each child PET to execute in its own Pthread.
!   By default, {\tt .false.}, single PETs spawned from a parent PET
!   execute in the same thread (or MPI process) as the parent PET. Multiple
!   child PETs spawned by the same parent PET always execute as their own
!   Pthreads.
! \item[{[rc]}]
!   Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOP
!------------------------------------------------------------------------------
    integer :: localrc                     ! local error status

    ! initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit,gridcomp,rc)

    ! call Comp method
    call ESMF_CompSetVMMinThreads(gridcomp%compp, maxPeCountPerPet, &
      prefIntraProcess, prefIntraSsi, prefInterSsi, pthreadMinStackSize, &
      forceChildPthreads, rc=localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS
  end subroutine ESMF_GridCompSetVMMinThreads
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompValidate"
!BOP
! !IROUTINE: ESMF_GridCompValidate - Check validity of a GridComp
!
! !INTERFACE:
  subroutine ESMF_GridCompValidate(gridcomp, keywordEnforcer, rc)
!
! !ARGUMENTS:
    type(ESMF_GridComp), intent(in)            :: gridcomp
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    integer,             intent(out), optional :: rc
!
! !STATUS:
! \begin{itemize}
! \item\apiStatusCompatibleVersion{5.2.0r}
! \end{itemize}
!
! !DESCRIPTION:
! Currently all this method does is to check that the {\tt gridcomp}
! was created.
!
! The arguments are:
! \begin{description}
! \item[gridcomp]
!   {\tt ESMF\_GridComp} to validate.
! \item[{[rc]}]
!   Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOP
!------------------------------------------------------------------------------
    integer :: localrc                        ! local return code

    ! Initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit,gridcomp,rc)

    ! call Comp method
    call ESMF_CompValidate(gridcomp%compp, rc=localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS
  end subroutine ESMF_GridCompValidate
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompWait"
!BOP
! !IROUTINE: ESMF_GridCompWait - Wait for a GridComp to return
!
! !INTERFACE:
  subroutine ESMF_GridCompWait(gridcomp, keywordEnforcer, syncflag, &
    timeout, timeoutFlag, userRc, rc)
!
! !ARGUMENTS:
    type(ESMF_GridComp),  intent(inout)         :: gridcomp
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    type(ESMF_Sync_Flag), intent(in),  optional :: syncflag
    integer,              intent(in),  optional :: timeout
    logical,              intent(out), optional :: timeoutFlag
    integer,              intent(out), optional :: userRc
    integer,              intent(out), optional :: rc
!
! !STATUS:
! \begin{itemize}
! \item\apiStatusCompatibleVersion{5.2.0r}
! \item\apiStatusModifiedSinceVersion{5.2.0r}
! \begin{description}
! \item[5.3.0] Added argument {\tt timeout}.
!              Added argument {\tt timeoutFlag}.
!              The new arguments provide access to the fault-tolerant component
!              features.
! \end{description}
! \end{itemize}
!
! !DESCRIPTION:
! When executing asynchronously, wait for an {\tt ESMF\_GridComp} to return.
!
! The arguments are:
! \begin{description}
! \item[gridcomp]
!   {\tt ESMF\_GridComp} to wait for.
! \item[{[syncflag]}]
!   Blocking behavior of this method call. See section \ref{const:sync}
!   for a list of valid blocking options. Default option is
!   {\tt ESMF\_SYNC\_VASBLOCKING} which blocks PETs and their spawned off threads
!   across each VAS but does not synchronize PETs that run in different VASs.
! \item[{[timeout]}]
!   The maximum period in seconds the actual component is allowed to execute
!   a previously invoked component method before it must communicate back to
!   the dual component. If the actual component does not communicate back in
!   the specified time, a timeout condition is raised on the dual side (this
!   side). The default is 3600, i.e. 1 hour. The {\tt timeout} argument is only
!   supported for connected dual components.
! \item[{[timeoutFlag]}]
!   Returns {\tt .true.} if the timeout was reached, {\tt .false.} otherwise.
!   If {\tt timeoutFlag} was {\em not} provided, a timeout condition will lead
!   to a return code of {\tt rc \textbackslash = ESMF\_SUCCESS}. Otherwise the
!   return value of {\tt timeoutFlag} is the sole indicator of a timeout
!   condition.
! \item[{[userRc]}]
!   Return code set by {\tt userRoutine} before returning.
! \item[{[rc]}]
!   Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOP
!------------------------------------------------------------------------------
    integer :: localrc                     ! local error status

    ! initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit,gridcomp,rc)

    ! check consistency between timeout argument and component argument
    if (present(timeout).and. &
      .not.ESMF_CompIsDualConnected(gridcomp%compp, rc=localrc)) then
      call ESMF_LogSetError(ESMF_RC_ARG_INCOMP, &
        msg="'timeout' argument is only allowed for connected dual components",&
        ESMF_CONTEXT, rcToReturn=rc)
      return
    endif

    ! call Comp method
    call ESMF_CompWait(gridcomp%compp, syncflag=syncflag, timeout=timeout, &
      userRc=userRc, rc=localrc)
    ! conditionally filter out the RC_TIMEOUT and return success
    if (present(timeoutFlag)) then
      timeoutFlag = .false. ! initialize
      if ((localrc==ESMF_RC_TIMEOUT).or.(localrc==ESMC_RC_TIMEOUT)) then
        timeoutFlag = .true.      ! indicate timeout through flag argument
        localrc = ESMF_SUCCESS    ! do not raise error condition on user level
      endif
    endif
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS
  end subroutine ESMF_GridCompWait
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompWriteRestart"
!BOP
! !IROUTINE: ESMF_GridCompWriteRestart - Call the GridComp's write restart routine
!
! !INTERFACE:
  recursive subroutine ESMF_GridCompWriteRestart(gridcomp, keywordEnforcer, &
    importState, exportState, clock, syncflag, phase, timeout, timeoutFlag, &
    userRc, rc)
!
! !ARGUMENTS:
    type(ESMF_GridComp),  intent(inout)           :: gridcomp
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    type(ESMF_State),     intent(inout), optional :: importState
    type(ESMF_State),     intent(inout), optional :: exportState
    type(ESMF_Clock),     intent(inout), optional :: clock
    type(ESMF_Sync_Flag), intent(in),    optional :: syncflag
    integer,              intent(in),    optional :: phase
    integer,              intent(in),    optional :: timeout
    logical,              intent(out),   optional :: timeoutFlag
    integer,              intent(out),   optional :: userRc
    integer,              intent(out),   optional :: rc
!
! !STATUS:
! \begin{itemize}
! \item\apiStatusCompatibleVersion{5.2.0r}
! \item\apiStatusModifiedSinceVersion{5.2.0r}
! \begin{description}
! \item[5.3.0] Added argument {\tt timeout}.
!              Added argument {\tt timeoutFlag}.
!              The new arguments provide access to the fault-tolerant component
!              features.
! \end{description}
! \end{itemize}
!
! !DESCRIPTION:
! Call the associated user write restart routine for
! an {\tt ESMF\_GridComp}.
!
! The arguments are:
! \begin{description}
! \item[gridcomp]
!   {\tt ESMF\_GridComp} to call run routine for.
! \item[{[importState]}]
!   {\tt ESMF\_State} containing import data. If not present, a dummy
!   argument will be passed to the user-supplied routine.  The
!   importState argument in the user code cannot be optional.
! \item[{[exportState]}]
!   {\tt ESMF\_State} containing export data. If not present, a dummy
!   argument will be passed to the user-supplied routine.  The
!   exportState argument in the user code cannot be optional.
! \item[{[clock]}]
!   External {\tt ESMF\_Clock} for passing in time information.
!   This is generally the parent component's clock, and will be treated
!   as read-only by the child component.  The child component can maintain
!   a private clock for its own internal time computations. If not present, a dummy
!   argument will be passed to the user-supplied routine.  The
!   clock argument in the user code cannot be optional.
! \item[{[syncflag]}]
!   Blocking behavior of this method call. See section \ref{const:sync}
!   for a list of valid blocking options. Default option is
!   {\tt ESMF\_SYNC\_VASBLOCKING} which blocks PETs and their spawned off threads
!   across each VAS but does not synchronize PETs that run in different VASs.
! \item[{[phase]}]
!   Component providers must document whether each of their
!   routines are {\em single-phase} or {\em multi-phase}.
!   Single-phase routines require only one invocation to complete
!   their work.
!   Multi-phase routines provide multiple subroutines to accomplish
!   the work, accommodating components which must complete part of their
!   work, return to the caller and allow other processing to occur,
!   and then continue the original operation.
!   For multiple-phase child components, this is the integer phase
!   number to be invoked.
!   For single-phase child components this argument is optional. The default is
!   1.
! \item[{[timeout]}]
!   The maximum period in seconds that this call will wait in communications
!   with the actual component, before returning with a timeout condition.
!   The default is 3600, i.e. 1 hour. The {\tt timeout} argument is only
!   supported for connected dual components.
! \item[{[timeoutFlag]}]
!   Returns {\tt .true.} if the timeout was reached, {\tt .false.} otherwise.
!   If {\tt timeoutFlag} was {\em not} provided, a timeout condition will lead
!   to a return code of {\tt rc \textbackslash = ESMF\_SUCCESS}. Otherwise the
!   return value of {\tt timeoutFlag} is the sole indicator of a timeout
!   condition.
! \item[{[userRc]}]
!   Return code set by {\tt userRoutine} before returning.
! \item[{[rc]}]
!   Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOP
!------------------------------------------------------------------------------
    integer :: localrc                        ! local return code
    integer :: timeoutArg

    ! initialize return code; assume routine not implemented
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit,gridcomp,rc)
    ESMF_INIT_CHECK_DEEP(ESMF_ClockGetInit,clock,rc)

    ! check consistency between timeout argument and component argument
    if (present(timeout).and. &
      .not.ESMF_CompIsDualConnected(gridcomp%compp, rc=localrc)) then
      call ESMF_LogSetError(ESMF_RC_ARG_INCOMP, &
        msg="'timeout' argument is only allowed for connected dual components",&
        ESMF_CONTEXT, rcToReturn=rc)
      return
    endif

    timeoutArg = ESMF_DEFAULT_TIMEOUT ! default 1h
    if (present(timeout)) timeoutArg = timeout

    ! call Comp method
    call ESMF_CompExecute(gridcomp%compp, method=ESMF_METHOD_WRITERESTART, &
      importState=importState, exportState=exportState, clock=clock, &
      syncflag=syncflag, phase=phase, timeout=timeoutArg, &
      userRc=userRc, rc=localrc)
    ! conditionally filter out the RC_TIMEOUT and return success
    if (present(timeoutFlag)) then
      timeoutFlag = .false. ! initialize
      if ((localrc==ESMF_RC_TIMEOUT).or.(localrc==ESMC_RC_TIMEOUT)) then
        timeoutFlag = .true.      ! indicate timeout through flag argument
        localrc = ESMF_SUCCESS    ! do not raise error condition on user level
      endif
    endif
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! return successfully
    if (present(rc)) rc = ESMF_SUCCESS
  end subroutine ESMF_GridCompWriteRestart
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_GridCompGetInit"
!BOPI
! !IROUTINE:  ESMF_GridCompGetInit - Get initialization status.

! !INTERFACE:
  recursive function ESMF_GridCompGetInit(d) result (GridCompGetInit)
!
! !RETURN VALUE:
    ESMF_INIT_TYPE :: GridCompGetInit
!
! !ARGUMENTS:
    type(ESMF_GridComp), intent(in), optional :: d
!
! !DESCRIPTION:
! Get the initialization status of the Deep class {\tt GridComp}.
!
! The arguments are:
! \begin{description}
! \item[d]
!   {\tt ESMF\_GridComp} from which to retrieve status.
! \end{description}
!
!EOPI
!------------------------------------------------------------------------------
    if (present(d)) then
      GridCompGetInit = ESMF_INIT_GET(d)
    else
      GridCompGetInit = ESMF_INIT_CREATED
    endif
  end function ESMF_GridCompGetInit
!------------------------------------------------------------------------------

end module ESMF_GridCompMod