ESMF_CplComp.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_CplComp.F90"
!==============================================================================
!
! ESMF Coupler Cplcomp module
module ESMF_CplCompMod
!
!==============================================================================
!
! This file contains the Coupler Cplcomp class definition and all
!   Coupler Cplcomp class methods.
!
!------------------------------------------------------------------------------
! INCLUDES
#include "ESMF.h"

!------------------------------------------------------------------------------
!BOPI
! !MODULE: ESMF_CplCompMod - Coupler Component class.
!
! !DESCRIPTION:
!
! The code in this file implements the Fortran interfaces to the
! {\tt ESMF\_CplComp} 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_CompMod
  use ESMF_InitMacrosMod
  use ESMF_IOUtilMod

  implicit none

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

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

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

  public ESMF_CplCompCreate
  public ESMF_CplCompDestroy
  public ESMF_CplCompFinalize
  public ESMF_CplCompFinalizeAct
  public ESMF_CplCompGet
  public ESMF_CplCompGetEPPhaseCount
  public ESMF_CplCompInitialize
  public ESMF_CplCompInitializeAct
  public ESMF_CplCompIsCreated
  public ESMF_CplCompIsPetLocal
  public ESMF_CplCompPrint
  public ESMF_CplCompReadRestart
  public ESMF_CplCompRun
  public ESMF_CplCompRunAct
  public ESMF_CplCompServiceLoop
  public ESMF_CplCompSet
  public ESMF_CplCompSetEntryPoint
  public ESMF_CplCompSetServices
  public ESMF_CplCompSetVM
  public ESMF_CplCompSetVMMaxPEs
  public ESMF_CplCompSetVMMaxThreads
  public ESMF_CplCompSetVMMinThreads
  public ESMF_CplCompValidate
  public ESMF_CplCompWait
  public ESMF_CplCompWriteRestart

! - ESMF-internal methods:
  public ESMF_CplCompGetInit

!EOPI

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

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

!------------------------------------------------------------------------------
  interface ESMF_CplCompSetServices
    module procedure ESMF_CplCompSetServices
    module procedure ESMF_CplCompSetServicesShObj
    module procedure ESMF_CplCompSetServicesComp
    module procedure ESMF_CplCompSetServicesSock
  end interface
!------------------------------------------------------------------------------

!------------------------------------------------------------------------------
  interface ESMF_CplCompSetVM
    module procedure ESMF_CplCompSetVM
    module procedure ESMF_CplCompSetVMShObj
  end interface
!------------------------------------------------------------------------------

!===============================================================================
! CplCompOperator() interfaces
!===============================================================================

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


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

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


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

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


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

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

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


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

contains

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


!-------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_CplCompEQ()"
!BOPI
! !IROUTINE:  ESMF_CplCompEQ - Compare two CplComps for equality
!
! !INTERFACE:
  impure elemental function ESMF_CplCompEQ(cplcomp1, cplcomp2)
!
! !RETURN VALUE:
    logical :: ESMF_CplCompEQ

! !ARGUMENTS:
    type(ESMF_CplComp), intent(in) :: cplcomp1
    type(ESMF_CplComp), intent(in) :: cplcomp2

! !DESCRIPTION:
!   Test if both {\tt cplcomp1} and {\tt cplcomp2} alias the same ESMF CplComp
!   object.
!
!EOPI
!-------------------------------------------------------------------------------

    ESMF_INIT_TYPE ccinit1, ccinit2
    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
    ccinit1 = ESMF_CplCompGetInit(cplcomp1)
    ccinit2 = ESMF_CplCompGetInit(cplcomp2)

    ! TODO: this line must remain split in two for SunOS f90 8.3 127000-03
    if (ccinit1 .eq. ESMF_INIT_CREATED .and. &
      ccinit2 .eq. ESMF_INIT_CREATED) then
      ESMF_CplCompEQ = associated(cplcomp1%compp,cplcomp2%compp)
    else
      ESMF_CplCompEQ = ESMF_FALSE
    endif

  end function ESMF_CplCompEQ
!-------------------------------------------------------------------------------


!-------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_CplCompNE()"
!BOPI
! !IROUTINE:  ESMF_CplCompNE - Compare two CplComps for non-equality
!
! !INTERFACE:
  impure elemental function ESMF_CplCompNE(cplcomp1, cplcomp2)
!
! !RETURN VALUE:
    logical :: ESMF_CplCompNE

! !ARGUMENTS:
    type(ESMF_CplComp), intent(in) :: cplcomp1
    type(ESMF_CplComp), intent(in) :: cplcomp2

! !DESCRIPTION:
!   Test if both {\tt cplcomp1} and {\tt cplcomp2} alias the same ESMF CplComp
!   object.
!
!EOPI
!-------------------------------------------------------------------------------

    ESMF_INIT_TYPE ccinit1, ccinit2
    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_CplCompNE = .not.ESMF_CplCompEQ(cplcomp1, cplcomp2)

  end function ESMF_CplCompNE
!-------------------------------------------------------------------------------

!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_CplCompCreate"
!BOP
! !IROUTINE: ESMF_CplCompCreate - Create a CplComp
!
! !INTERFACE:
  recursive function ESMF_CplCompCreate(keywordEnforcer, config, configFile, &
    clock, petList, devList, contextflag, name, rc)
!
! !RETURN VALUE:
    type(ESMF_CplComp) :: ESMF_CplCompCreate
!
! !ARGUMENTS:
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    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}
! \item[8.6.0] Added argument {\tt devList} to support management of accelerator
!   devices.
! \end{description}
! \end{itemize}
!
! !DESCRIPTION:
! This interface creates an {\tt ESMF\_CplComp} 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\_CplComp}.
!
! The arguments are:
! \begin{description}
! \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\_CplComp} 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\_CplComp}.  This name can be altered
!   from within the {\tt ESMF\_CplComp} 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_CplComp)            :: cplcomp
    integer :: localrc                                ! local error localrc

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

    ! Initialize the pointer to null.
    nullify(ESMF_CplCompCreate%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="Component class", &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! call Comp method
    call ESMF_CompConstruct(compclass, ESMF_COMPTYPE_CPL, 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

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

    ! Set return values
    ESMF_CplCompCreate%compp => compclass

    ESMF_INIT_SET_CREATED(ESMF_CplCompCreate)

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

  end function ESMF_CplCompCreate
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_CplCompDestroy"
!BOP
! !IROUTINE: ESMF_CplCompDestroy - Release resources associated with a CplComp

! !INTERFACE:
  recursive subroutine ESMF_CplCompDestroy(cplcomp, keywordEnforcer, &
    timeout, timeoutFlag, rc)
!
! !ARGUMENTS:
    type(ESMF_CplComp), intent(inout)          :: cplcomp
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\_CplComp}, releasing the resources associated
! with the object.
!
! The arguments are:
! \begin{description}
! \item[cplcomp]
!   Release all resources associated with this {\tt ESMF\_CplComp}
!   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 localrc

    ! 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_CplCompGetInit,cplcomp,rc)

    ! Check to see if already destroyed
    if (.not.associated(cplcomp%compp)) then
      if (ESMF_LogFoundError(ESMF_RC_OBJ_BAD, &
        msg="CplComp 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(cplcomp%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(cplcomp%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(cplcomp%compp%base, ESMF_STATUS_INVALID, &
      rc=localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ESMF_INIT_SET_DELETED(cplcomp)

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

  end subroutine ESMF_CplCompDestroy
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_CplCompFinalize"
!BOP
! !IROUTINE: ESMF_CplCompFinalize - Call the CplComp's finalize routine
!
! !INTERFACE:
  recursive subroutine ESMF_CplCompFinalize(cplcomp, keywordEnforcer, &
    importState, exportState, clock, syncflag, phase, timeout, timeoutFlag, &
    userRc, rc)
!
!
! !ARGUMENTS:
    type(ESMF_CplComp),   intent(inout)           :: cplcomp
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\_CplComp}.
!
! The arguments are:
! \begin{description}
! \item[cplcomp]
!   The {\tt ESMF\_CplComp} to call finalize 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_CplCompGetInit,cplcomp,rc)

    ! check consistency between timeout argument and component argument
    if (present(timeout).and. &
      .not.ESMF_CompIsDualConnected(cplcomp%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(cplcomp%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_CplCompFinalize
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_CplCompFinalizeAct"
!BOPI
! !IROUTINE: ESMF_CplCompFinalizeAct - Call the CplComp's finalize routine
!
! !INTERFACE:
  recursive subroutine ESMF_CplCompFinalizeAct(cplcomp, importState, exportState, &
    clock, syncflag, phase, userRc, rc)
!
!
! !ARGUMENTS:
    type(ESMF_CplComp),   intent(inout)           :: cplcomp
    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\_CplCompFinalize} 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_CplCompGetInit,cplcomp,rc)

    ! call Comp method
    call ESMF_CompExecute(cplcomp%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_CplCompFinalizeAct
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_CplCompGet"
!BOP
! !IROUTINE: ESMF_CplCompGet - Get CplComp information
!
! !INTERFACE:
  subroutine ESMF_CplCompGet(cplcomp, keywordEnforcer, configIsPresent, config, &
    configFileIsPresent, configFile, clockIsPresent, clock, localPet, &
    petCount, contextflag, currentMethod, currentPhase, vmIsPresent, &
    vm, name, rc)
!
! !ARGUMENTS:
    type(ESMF_CplComp),      intent(in)            :: cplcomp
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    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
    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}
! \end{itemize}
!
! !DESCRIPTION:
! Get information about an {\tt ESMF\_CplComp} object.
!
! The arguments are:
! \begin{description}
! \item[cplcomp]
!   The {\tt ESMF\_CplComp} object being queried.
! \item[{[configIsPresent]}]
!   {\tt .true.} if {\tt config} was set in CplComp 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 CplComp. If unsure, get {\tt configIsPresent} first to determine
!   the status.
! \item[{[configFileIsPresent]}]
!   {\tt .true.} if {\tt configFile} was set in CplComp 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 CplComp. If unsure, get {\tt configFileIsPresent} first to determine
!   the status.
! \item[{[clockIsPresent]}]
!   {\tt .true.} if {\tt clock} was set in CplComp 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 CplComp. If unsure, get {\tt clockIsPresent} first to determine
!   the status.
! \item[{[localPet]}]
!   Return the local PET id within the {\tt ESMF\_CplComp} object.
! \item[{[petCount]}]
!   Return the number of PETs in the the {\tt ESMF\_CplComp} object.
! \item[{[contextflag]}]
!   Return the {\tt ESMF\_Context\_Flag} for this {\tt ESMF\_CplComp}.
!   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\_CplComp} execution.
!   See section \ref{const:method}  for a complete list of valid options.
! \item[{[currentPhase]}]
!   Return the current {\tt phase} of the {\tt ESMF\_CplComp} execution.
! \item[{[vmIsPresent]}]
!   {\tt .true.} if {\tt vm} was set in CplComp 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 CplComp. If unsure, get {\tt vmIsPresent} first to determine
!   the status.
! \item[{[name]}]
!   Return the name of the {\tt ESMF\_CplComp}.
! \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_CplCompGetInit,cplcomp,rc)

    ! call Comp method
    call ESMF_CompGet(cplcomp%compp, name=name, vm=vm, contextflag=contextflag,&
      clock=clock, configFile=configFile, config=config, &
      currentMethod=currentMethod, currentPhase=currentPhase, &
      localPet=localPet, petCount=petCount, compStatus=compStatus, rc=localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

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

    ! call Comp method
    call ESMF_CompStatusGet(compStatus, &
      clockIsPresent = clockIsPresent, &
      configIsPresent = configIsPresent, &
      configFileIsPresent = configFileIsPresent, &
      vmIsPresent = vmIsPresent, &
      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_CplCompGet
!------------------------------------------------------------------------------


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

! !ARGUMENTS:
    type(ESMF_CplComp),     intent(in)            :: cplcomp
    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[cplcomp]
!   An {\tt ESMF\_CplComp} 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_CplCompGetInit, cplcomp, rc)

    call c_ESMC_GetEntryPointPhaseCount(cplcomp, 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_CplCompGetEPPhaseCount
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
!BOP
! !IROUTINE: ESMF_CplCompGetInternalState - Get private data block pointer
!
! !INTERFACE:
! subroutine ESMF_CplCompGetInternalState(cplcomp, wrappedDataPointer, rc)
!
! !ARGUMENTS:
!   type(ESMF_CplComp)              :: cplcomp
!   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\_CplComp} at any time after
! {\tt ESMF\_CplCompSetInternalState} 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\_CplComp},
! 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\_CplCompSetInternalState} 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\_CplCompSetInternalState}.
!
! Only the {\em last} data block set via
! {\tt ESMF\_CplCompSetInternalState} 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[cplcomp]
!   An {\tt ESMF\_CplComp} 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\_CplCompSetInternalState} 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_CplCompInitialize"
!BOP
! !IROUTINE: ESMF_CplCompInitialize - Call the CplComp's initialize routine
!
! !INTERFACE:
  recursive subroutine ESMF_CplCompInitialize(cplcomp, keywordEnforcer, &
    importState, exportState, clock, syncflag, phase, timeout, timeoutFlag, &
    userRc, rc)
!
!
! !ARGUMENTS:
    type(ESMF_CplComp),   intent(inout)           :: cplcomp
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\_CplComp}.
!
! The arguments are:
! \begin{description}
! \item[cplcomp]
!   {\tt ESMF\_CplComp} 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_CplCompGetInit,cplcomp,rc)

    ! check consistency between timeout argument and component argument
    if (present(timeout).and. &
      .not.ESMF_CompIsDualConnected(cplcomp%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(cplcomp%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_CplCompInitialize
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_CplCompInitializeAct"
!BOPI
! !IROUTINE: ESMF_CplCompInitializeAct - Call the CplComp's initialize routine
!
! !INTERFACE:
  recursive subroutine ESMF_CplCompInitializeAct(cplcomp, importState, &
    exportState, clock, syncflag, phase, userRc, rc)
!
!
! !ARGUMENTS:
    type(ESMF_CplComp),   intent(inout)           :: cplcomp
    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\_CplCompInitialize} 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_CplCompGetInit,cplcomp,rc)

    ! call Comp method
    call ESMF_CompExecute(cplcomp%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_CplCompInitializeAct
!------------------------------------------------------------------------------

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

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

! !DESCRIPTION:
!   Return {\tt .true.} if the {\tt cplcomp} 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[cplcomp]
!     {\tt ESMF\_CplComp} queried.
!   \item[{[rc]}]
!     Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
!   \end{description}
!
!EOP
  !-----------------------------------------------------------------------------
    ESMF_CplCompIsCreated = .false.   ! initialize
    if (present(rc)) rc = ESMF_SUCCESS
    if (ESMF_CplCompGetInit(cplcomp)==ESMF_INIT_CREATED) &
      ESMF_CplCompIsCreated = .true.
  end function
!------------------------------------------------------------------------------

!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_CplCompIsPetLocal"
!BOP
! !IROUTINE: ESMF_CplCompIsPetLocal - Inquire if this CplComp is to execute on the calling PET
!
! !INTERFACE:
  recursive function ESMF_CplCompIsPetLocal(cplcomp, keywordEnforcer, rc)
!
! !RETURN VALUE:
    logical :: ESMF_CplCompIsPetLocal
!
! !ARGUMENTS:
    type(ESMF_CplComp), intent(in)            :: cplcomp
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\_CplComp} 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[cplcomp]
!   {\tt ESMF\_CplComp} 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_CplCompIsPetLocal = .false.

    ESMF_INIT_CHECK_DEEP(ESMF_CplCompGetInit,cplcomp,rc)

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

    ESMF_CplCompIsPetLocal = localresult

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


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_CplCompPrint"
!BOP
! !IROUTINE:  ESMF_CplCompPrint - Print CplComp information
!
! !INTERFACE:
  subroutine ESMF_CplCompPrint(cplcomp, keywordEnforcer, rc)
!
! !ARGUMENTS:
    type(ESMF_CplComp), intent(in)            :: cplcomp
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\_CplComp} to {\tt stdout}. \\
!
! The arguments are:
! \begin{description}
! \item[cplcomp]
!   {\tt ESMF\_CplComp} 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_CplCompGetInit,cplcomp,rc)

    write (ESMF_UtilIOStdout,*) "Coupler Component:"
    ! call Comp method
    call ESMF_CompPrint(cplcomp%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_CplCompPrint
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_CplCompReadRestart"
!BOP
! !IROUTINE: ESMF_CplCompReadRestart -- Call the CplComp's read restart routine
!
! !INTERFACE:
  recursive subroutine ESMF_CplCompReadRestart(cplcomp, keywordEnforcer, &
    importState, exportState, clock, syncflag, phase, timeout, timeoutFlag, &
    userRc, rc)
!
! !ARGUMENTS:
    type(ESMF_CplComp),   intent(inout)           :: cplcomp
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\_CplComp}.
!
! The arguments are:
! \begin{description}
! \item[cplcomp]
!   {\tt ESMF\_CplComp} 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_CplCompGetInit,cplcomp,rc)

    ! check consistency between timeout argument and component argument
    if (present(timeout).and. &
      .not.ESMF_CompIsDualConnected(cplcomp%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(cplcomp%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_CplCompReadRestart
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_CplCompRun"
!BOP
! !IROUTINE: ESMF_CplCompRun - Call the CplComp's run routine
!
! !INTERFACE:
  recursive subroutine ESMF_CplCompRun(cplcomp, keywordEnforcer, &
    importState, exportState, clock, syncflag, phase, timeout, timeoutFlag, &
    userRc, rc)
!
! !ARGUMENTS:
    type(ESMF_CplComp),   intent(inout)           :: cplcomp
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\_CplComp}.
!
! The arguments are:
! \begin{description}
! \item[cplcomp]
!   {\tt ESMF\_CplComp} to call run 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_CplCompGetInit,cplcomp,rc)

    ! check consistency between timeout argument and component argument
    if (present(timeout).and. &
      .not.ESMF_CompIsDualConnected(cplcomp%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(cplcomp%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_CplCompRun
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_CplCompRunAct"
!BOPI
! !IROUTINE: ESMF_CplCompRunAct - Call the CplComp's run routine
!
! !INTERFACE:
  recursive subroutine ESMF_CplCompRunAct(cplcomp, importState, exportState, &
    clock, syncflag, phase, userRc, rc)
!
! !ARGUMENTS:
    type(ESMF_CplComp),   intent(inout)           :: cplcomp
    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\_CplCompRun} 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_CplCompGetInit,cplcomp,rc)

    ! call Comp method
    call ESMF_CompExecute(cplcomp%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_CplCompRunAct
!------------------------------------------------------------------------------


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

! !INTERFACE:
  recursive subroutine ESMF_CplCompServiceLoop(cplcomp, keywordEnforcer, &
    importState, exportState, clock, syncflag, port, timeout, timeoutFlag, rc)
!
! !ARGUMENTS:
    type(ESMF_CplComp),   intent(inout)           :: cplcomp
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\_CplComp}.
! 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[cplcomp]
!   {\tt ESMF\_CplComp} 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\_CplCompServiceLoop()}, 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_CplCompGetInit,cplcomp,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(cplcomp%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_CplCompServiceLoop
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_CplCompSet"
!BOP
! !IROUTINE: ESMF_CplCompSet - Set or reset information about the CplComp
!
! !INTERFACE:
  subroutine ESMF_CplCompSet(cplcomp, keywordEnforcer, config, configFile, &
    clock, name, rc)
!
! !ARGUMENTS:
    type(ESMF_CplComp), intent(inout)         :: cplcomp
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    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}
! \end{itemize}
!
! !DESCRIPTION:
! Sets or resets information about an {\tt ESMF\_CplComp}.
!
! The arguments are:
! \begin{description}
! \item[cplcomp]
!   {\tt ESMF\_CplComp} to change.
! \item[{[name]}]
!   Set the name of the {\tt ESMF\_CplComp}.
! \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\_CplComp}.
! \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_CplCompGetInit,cplcomp,rc)
    ESMF_INIT_CHECK_DEEP(ESMF_ConfigGetInit,config,rc)
    ESMF_INIT_CHECK_DEEP(ESMF_ClockGetInit,clock,rc)

    if (cplcomp%isNamedAlias .and. present(name)) then
      ! set NamedAlias name
      cplcomp%name = trim(name)
      ! call Comp method (without name)
      call ESMF_CompSet(cplcomp%compp, 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(cplcomp%compp, name=name, 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_CplCompSet
!------------------------------------------------------------------------------


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

! !ARGUMENTS:
    type(ESMF_CplComp),     intent(inout)         :: cplcomp
    type(ESMF_Method_Flag), intent(in)            :: methodflag
    interface
      subroutine userRoutine(cplcomp, importState, exportState, clock, rc)
        use ESMF_CompMod
        use ESMF_StateMod
        use ESMF_ClockMod
        implicit none
        type(ESMF_CplComp)          :: cplcomp      ! 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[cplcomp]
!   An {\tt ESMF\_CplComp} 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 {\tt methodflag}.
!   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}
! \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_CplCompGetInit, cplcomp, rc)

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

    call c_ESMC_SetEntryPoint(cplcomp, 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_CplCompSetEntryPoint
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
!BOP
! !IROUTINE: ESMF_CplCompSetInternalState - Set private data block pointer
!
! !INTERFACE:
! subroutine ESMF_CplCompSetInternalState(cplcomp, wrappedDataPointer, rc)
!
! !ARGUMENTS:
!   type(ESMF_CplComp)              :: cplcomp
!   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\_CplComp} 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\_CplComp},
! 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\_CplCompGetInternalState} call retrieves the data pointer.
!
! Only the {\em last} data block set via
! {\tt ESMF\_CplCompSetInternalState} 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[cplcomp]
!   An {\tt ESMF\_CplComp} 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_CplCompSetServices"
!BOP
! !IROUTINE: ESMF_CplCompSetServices - Call user routine to register CplComp methods
!
! !INTERFACE:
  recursive subroutine ESMF_CplCompSetServices(cplcomp, userRoutine, &
     keywordEnforcer, userRc, rc)
!
! !ARGUMENTS:
    type(ESMF_CplComp), intent(inout)         :: cplcomp
    interface
      subroutine userRoutine(cplcomp, rc)
        use ESMF_CompMod
        implicit none
        type(ESMF_CplComp)         :: cplcomp  ! 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{CplComp: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[cplcomp]
!   Coupler 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\_CplCompSetEntryPoint()} 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_CplCompGetInit, cplcomp, rc)

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

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

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

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


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_CplCompSetServicesShObj"
!BOP
! !IROUTINE: ESMF_CplCompSetServices - Call user routine through name lookup, to register CplComp methods
!
! !INTERFACE:
  ! Private name; call using ESMF_CplCompSetServices()
  recursive subroutine ESMF_CplCompSetServicesShObj(cplcomp, userRoutine, &
    keywordEnforcer, sharedObj, userRoutineFound, userRc, rc)
!
! !ARGUMENTS:
    type(ESMF_CplComp),  intent(inout)         :: cplcomp
    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{CplComp: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[cplcomp]
!   Coupler 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(cplcomp, rc)
!         type(ESMF_CplComp)   :: cplcomp    ! 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\_CplCompSetEntryPoint()} 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_CplCompGetInit, cplcomp, rc)

    if (present(sharedObj)) then
      call c_ESMC_SetServicesShObj(cplcomp, userRoutine, sharedObj, &
        userRoutineFoundHelp, localUserRc, localrc)
    else
      call c_ESMC_SetServicesShObj(cplcomp, 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
      cplcomp%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_CplCompSetServicesShObj
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_CplCompSetServicesComp"
!BOP
! !IROUTINE: ESMF_CplCompSetServices - Set to serve as Dual Component for an Actual Component
!
! !INTERFACE:
  ! Private name; call using ESMF_CplCompSetServices()
  recursive subroutine ESMF_CplCompSetServicesComp(cplcomp, &
    actualCplcomp, keywordEnforcer, rc)
!
! !ARGUMENTS:
    type(ESMF_CplComp), intent(inout)         :: cplcomp
    type(ESMF_CplComp), intent(in)            :: actualCplcomp
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    integer,            intent(out), optional :: rc
!
! !DESCRIPTION:
! Set the services of a Coupler Component to serve a "dual" Component for an
! "actual" Component. The component tunnel is VM based.
!
! The arguments are:
! \begin{description}
! \item[cplcomp]
!   Dual Coupler Component.
! \item[actualCplcomp]
!   Actual Coupler 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_CplCompGetInit, cplcomp, rc)
    ESMF_INIT_CHECK_DEEP(ESMF_CplCompGetInit, actualCplcomp, rc)

    ! access the petList of the actualCplcomp 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(actualCplcomp%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(cplcomp, cplcomp%compp%compTunnel, &
      actualCplcomp, actualCompRootPet, localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

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

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


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_CplCompSetServicesSock"
!BOP
! !IROUTINE: ESMF_CplCompSetServices - Set to serve as Dual Component for an Actual Component through sockets
!
! !INTERFACE:
  ! Private name; call using ESMF_CplCompSetServices()
  recursive subroutine ESMF_CplCompSetServicesSock(cplcomp, port, &
    keywordEnforcer, server, timeout, timeoutFlag, rc)
!
! !ARGUMENTS:
    type(ESMF_CplComp), intent(inout)         :: cplcomp
    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 Coupler Component to serve a "dual" Component for an
! "actual" Component. The component tunnel is socket based.
!
! The arguments are:
! \begin{description}
! \item[cplcomp]
!   Dual Coupler 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_CplCompGetInit, cplcomp, rc)

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

    if (present(server)) then
      call c_ESMC_SetServicesSock(cplcomp, cplcomp%compp%compTunnel, &
        port, server, timeoutArg, localrc)
    else
      call c_ESMC_SetServicesSock(cplcomp, cplcomp%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
    cplcomp%compp%compStatus%vmIsPresent = .true.

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


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_CplCompSetVM"
!BOP
! !IROUTINE: ESMF_CplCompSetVM - Call user routine to set CplComp VM properties
!
! !INTERFACE:
  recursive subroutine ESMF_CplCompSetVM(cplcomp, userRoutine, &
    keywordEnforcer, userRc, rc)
! !ARGUMENTS:
    type(ESMF_CplComp), intent(inout)         :: cplcomp
    interface
      subroutine userRoutine(cplcomp, rc)
        use ESMF_CompMod
        implicit none
        type(ESMF_CplComp)         :: cplcomp  ! 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[cplcomp]
!   Coupler 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\_CplCompSetVMxxx()} methods to set the properties of the VM
!   associated with the Coupler 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_CplCompGetInit, cplcomp, rc)

    call c_ESMC_SetVM(cplcomp, 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_CplCompSetVM
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_CplCompSetVMShObj"
!BOP
! !IROUTINE: ESMF_CplCompSetVM - Call user routine through name lookup, to set CplComp VM properties
! !INTERFACE:
  ! Private name; call using ESMF_CplCompSetVM()
  recursive subroutine ESMF_CplCompSetVMShObj(cplcomp, userRoutine, &
    keywordEnforcer, sharedObj, userRoutineFound, userRc, rc)
!
! !ARGUMENTS:
    type(ESMF_CplComp),  intent(inout)         :: cplcomp
    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[cplcomp]
!   Coupler 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(cplcomp, rc)
!         type(ESMF_CplComp)   :: cplcomp     ! 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\_CplCompSetVMxxx()} methods to set the properties of the VM
!   associated with the Coupler 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_CplCompGetInit, cplcomp, rc)

    if (present(sharedObj)) then
      call c_ESMC_SetVMShObj(cplcomp, userRoutine, sharedObj, &
        userRoutineFoundHelp, localUserRc, localrc)
    else
      call c_ESMC_SetVMShObj(cplcomp, 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_CplCompSetVMShObj
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_CplCompSetVMMaxPEs"
!BOP
! !IROUTINE: ESMF_CplCompSetVMMaxPEs - Associate PEs with PETs in CplComp VM
!
! !INTERFACE:
  subroutine ESMF_CplCompSetVMMaxPEs(cplcomp, keywordEnforcer, &
    maxPeCountPerPet, prefIntraProcess, prefIntraSsi, prefInterSsi, &
    pthreadMinStackSize, forceChildPthreads, rc)
!
! !ARGUMENTS:
    type(ESMF_CplComp),  intent(inout)         :: cplcomp
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\_CplComp}.
!   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\_CplCompSetVMMaxPEs()} is to allocate
!   multiple PEs per PET in a Component for user-level threading, e.g. OpenMP.
!
! The arguments are:
! \begin{description}
! \item[cplcomp]
!   {\tt ESMF\_CplComp} 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 localrc

    ! 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_CplCompGetInit,cplcomp,rc)

    ! call Comp method
    call ESMF_CompSetVMMaxPEs(cplcomp%compp, maxPeCountPerPet, &
      prefIntraProcess, prefIntraSsi, prefInterSsi, pthreadMinStackSize, &
      forceChildPthreads=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_CplCompSetVMMaxPEs
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_CplCompSetVMMaxThreads"
!BOP
! !IROUTINE: ESMF_CplCompSetVMMaxThreads - Set multi-threaded PETs in CplComp VM
!
! !INTERFACE:
  subroutine ESMF_CplCompSetVMMaxThreads(cplcomp, keywordEnforcer, &
    maxPetCountPerVas, prefIntraProcess, prefIntraSsi, prefInterSsi, &
    pthreadMinStackSize, forceChildPthreads, rc)
!
! !ARGUMENTS:
    type(ESMF_CplComp),  intent(inout)         :: cplcomp
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\_CplComp}.
!   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\_CplCompSetVMMaxThreads()} is to run a
!   Component multi-threaded with groups of PETs executing within a common
!   virtual address space.
!
! The arguments are:
! \begin{description}
! \item[cplcomp]
!   {\tt ESMF\_CplComp} 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 localrc

    ! 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_CplCompGetInit,cplcomp,rc)

    ! call Comp method
    call ESMF_CompSetVMMaxThreads(cplcomp%compp, maxPetCountPerVas, &
      prefIntraProcess, prefIntraSsi, prefInterSsi, pthreadMinStackSize, &
      forceChildPthreads=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_CplCompSetVMMaxThreads
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_CplCompSetVMMinThreads"
!BOP
! !IROUTINE: ESMF_CplCompSetVMMinThreads - Set a reduced threading level in CplComp VM
!
! !INTERFACE:
  subroutine ESMF_CplCompSetVMMinThreads(cplcomp, keywordEnforcer, &
    maxPeCountPerPet, prefIntraProcess, prefIntraSsi, prefInterSsi, &
    pthreadMinStackSize, forceChildPthreads, rc)
!
! !ARGUMENTS:
    type(ESMF_CplComp),  intent(inout)         :: cplcomp
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\_CplComp}.
!   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\_CplCompSetVMMinThreads()} is to run a
!   Component across a set of single-threaded PETs.
!
! The arguments are:
! \begin{description}
! \item[cplcomp]
!   {\tt ESMF\_CplComp} 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 localrc

    ! 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_CplCompGetInit,cplcomp,rc)

    ! call Comp method
    call ESMF_CompSetVMMinThreads(cplcomp%compp, maxPeCountPerPet, &
      prefIntraProcess, prefIntraSsi, prefInterSsi, pthreadMinStackSize, &
      forceChildPthreads=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_CplCompSetVMMinThreads
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_CplCompValidate"
!BOP
! !IROUTINE: ESMF_CplCompValidate -- Ensure the CplComp is internally consistent
!
! !INTERFACE:
  subroutine ESMF_CplCompValidate(cplcomp, keywordEnforcer, rc)
!
! !ARGUMENTS:
    type(ESMF_CplComp), intent(in)            :: cplcomp
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 cplcomp}
! was created.
!
! The arguments are:
! \begin{description}
! \item[cplcomp]
!   {\tt ESMF\_CplComp} 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_CplCompGetInit,cplcomp,rc)

    ! call Comp method
    call ESMF_CompValidate(cplcomp%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_CplCompValidate
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_CplCompWait"
!BOP
! !IROUTINE: ESMF_CplCompWait - Wait for a CplComp to return
!
! !INTERFACE:
  subroutine ESMF_CplCompWait(cplcomp, keywordEnforcer, syncflag, &
    timeout, timeoutFlag, userRc, rc)
!
! !ARGUMENTS:
    type(ESMF_CplComp),   intent(inout)         :: cplcomp
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\_CplComp} to return.
!
! The arguments are:
! \begin{description}
! \item[cplcomp]
!   {\tt ESMF\_CplComp} 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 localrc

    ! 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_CplCompGetInit,cplcomp,rc)

    ! check consistency between timeout argument and component argument
    if (present(timeout).and. &
      .not.ESMF_CompIsDualConnected(cplcomp%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(cplcomp%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_CplCompWait
!------------------------------------------------------------------------------


!------------------------------------------------------------------------------
#undef  ESMF_METHOD
#define ESMF_METHOD "ESMF_CplCompWriteRestart"
!BOP
! !IROUTINE: ESMF_CplCompWriteRestart -- Call the CplComp's write restart routine

! !INTERFACE:
  recursive subroutine ESMF_CplCompWriteRestart(cplcomp, keywordEnforcer, &
    importState, exportState, clock, syncflag, phase, timeout, timeoutFlag, &
    userRc, rc)
!
! !ARGUMENTS:
    type(ESMF_CplComp),   intent(inout)           :: cplcomp
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\_CplComp}.
!
! The arguments are:
! \begin{description}
! \item[cplcomp]
!   {\tt ESMF\_CplComp} 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_CplCompGetInit,cplcomp,rc)
    ESMF_INIT_CHECK_DEEP(ESMF_ClockGetInit,clock,rc)

    ! check consistency between timeout argument and component argument
    if (present(timeout).and. &
      .not.ESMF_CompIsDualConnected(cplcomp%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(cplcomp%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_CplCompWriteRestart
!------------------------------------------------------------------------------


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

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

end module ESMF_CplCompMod