ESMF_CompExecute Subroutine

public recursive subroutine ESMF_CompExecute(compp, method, importState, exportState, clock, syncflag, phase, port, timeout, userRc, rc)

Arguments

Type IntentOptional Attributes Name
type(ESMF_CompClass), pointer :: compp
type(ESMF_Method_Flag), intent(in) :: method
type(ESMF_State), intent(inout), optional :: importState
type(ESMF_State), intent(inout), optional :: exportState
type(ESMF_Clock), intent(in), optional :: clock
type(ESMF_Sync_Flag), intent(in), optional :: syncflag
integer, intent(in), optional :: phase
integer, intent(in), optional :: port
integer, intent(in), optional :: timeout
integer, intent(out), optional :: userRc
integer, intent(out), optional :: rc

Calls

proc~~esmf_compexecute~~CallsGraph proc~esmf_compexecute ESMF_CompExecute c_esmc_compwait c_esmc_compwait proc~esmf_compexecute->c_esmc_compwait c_esmc_ftablecallentrypointvm c_esmc_ftablecallentrypointvm proc~esmf_compexecute->c_esmc_ftablecallentrypointvm c_esmc_ftablesetstateargs c_esmc_ftablesetstateargs proc~esmf_compexecute->c_esmc_ftablesetstateargs proc~esmf_basegetstatus ESMF_BaseGetStatus proc~esmf_compexecute->proc~esmf_basegetstatus proc~esmf_clocksetthis ESMF_ClockSetThis proc~esmf_compexecute->proc~esmf_clocksetthis proc~esmf_compclassgetinit ESMF_CompClassGetInit proc~esmf_compexecute->proc~esmf_compclassgetinit proc~esmf_imerr ESMF_IMErr proc~esmf_compexecute->proc~esmf_imerr proc~esmf_logfounderror ESMF_LogFoundError proc~esmf_compexecute->proc~esmf_logfounderror proc~esmf_logseterror ESMF_LogSetError proc~esmf_compexecute->proc~esmf_logseterror proc~esmf_vmbarrier ESMF_VMBarrier proc~esmf_compexecute->proc~esmf_vmbarrier proc~esmf_vmgetcurrent ESMF_VMGetCurrent proc~esmf_compexecute->proc~esmf_vmgetcurrent proc~esmf_vmwtime ESMF_VMWtime proc~esmf_compexecute->proc~esmf_vmwtime proc~esmf_basegetstatus->proc~esmf_logfounderror c_esmc_basegetstatus c_esmc_basegetstatus proc~esmf_basegetstatus->c_esmc_basegetstatus proc~esmf_imerr->proc~esmf_logfounderror proc~esmf_initcheckdeep ESMF_InitCheckDeep proc~esmf_imerr->proc~esmf_initcheckdeep esmf_breakpoint esmf_breakpoint proc~esmf_logfounderror->esmf_breakpoint proc~esmf_logrc2msg ESMF_LogRc2Msg proc~esmf_logfounderror->proc~esmf_logrc2msg proc~esmf_logwrite ESMF_LogWrite proc~esmf_logfounderror->proc~esmf_logwrite proc~esmf_logseterror->esmf_breakpoint proc~esmf_logseterror->proc~esmf_logrc2msg proc~esmf_logseterror->proc~esmf_logwrite proc~esmf_vmbarrier->proc~esmf_imerr proc~esmf_vmbarrier->proc~esmf_logfounderror proc~esmf_vmbarrier->proc~esmf_vmgetcurrent c_esmc_vmbarrier c_esmc_vmbarrier proc~esmf_vmbarrier->c_esmc_vmbarrier proc~esmf_vmgetinit ESMF_VMGetInit proc~esmf_vmbarrier->proc~esmf_vmgetinit proc~esmf_vmgetcurrent->proc~esmf_logfounderror c_esmc_vmgetcurrent c_esmc_vmgetcurrent proc~esmf_vmgetcurrent->c_esmc_vmgetcurrent proc~esmf_vmwtime->proc~esmf_logfounderror c_esmc_vmwtime c_esmc_vmwtime proc~esmf_vmwtime->c_esmc_vmwtime c_esmc_loggeterrormsg c_esmc_loggeterrormsg proc~esmf_logrc2msg->c_esmc_loggeterrormsg proc~esmf_logwrite->c_esmc_vmwtime proc~esmf_logclose ESMF_LogClose proc~esmf_logwrite->proc~esmf_logclose proc~esmf_logflush ESMF_LogFlush proc~esmf_logwrite->proc~esmf_logflush proc~esmf_logopenfile ESMF_LogOpenFile proc~esmf_logwrite->proc~esmf_logopenfile proc~esmf_utiliounitflush ESMF_UtilIOUnitFlush proc~esmf_logwrite->proc~esmf_utiliounitflush proc~esmf_utilstring2array ESMF_UtilString2Array proc~esmf_logwrite->proc~esmf_utilstring2array proc~esmf_logclose->proc~esmf_logflush proc~esmf_logflush->proc~esmf_utiliounitflush proc~esmf_utilarray2string ESMF_UtilArray2String proc~esmf_logflush->proc~esmf_utilarray2string proc~esmf_logopenfile->proc~esmf_utiliounitflush proc~esmf_utiliounitget ESMF_UtilIOUnitGet proc~esmf_logopenfile->proc~esmf_utiliounitget

Called by

proc~~esmf_compexecute~~CalledByGraph proc~esmf_compexecute ESMF_CompExecute proc~esmf_compdestruct ESMF_CompDestruct proc~esmf_compdestruct->proc~esmf_compexecute proc~esmf_cplcompfinalize ESMF_CplCompFinalize proc~esmf_cplcompfinalize->proc~esmf_compexecute proc~esmf_cplcompfinalizeact ESMF_CplCompFinalizeAct proc~esmf_cplcompfinalizeact->proc~esmf_compexecute proc~esmf_cplcompinitialize ESMF_CplCompInitialize proc~esmf_cplcompinitialize->proc~esmf_compexecute proc~esmf_cplcompinitializeact ESMF_CplCompInitializeAct proc~esmf_cplcompinitializeact->proc~esmf_compexecute proc~esmf_cplcompreadrestart ESMF_CplCompReadRestart proc~esmf_cplcompreadrestart->proc~esmf_compexecute proc~esmf_cplcomprun ESMF_CplCompRun proc~esmf_cplcomprun->proc~esmf_compexecute proc~esmf_cplcomprunact ESMF_CplCompRunAct proc~esmf_cplcomprunact->proc~esmf_compexecute proc~esmf_cplcompserviceloop ESMF_CplCompServiceLoop proc~esmf_cplcompserviceloop->proc~esmf_compexecute proc~esmf_cplcompwriterestart ESMF_CplCompWriteRestart proc~esmf_cplcompwriterestart->proc~esmf_compexecute proc~esmf_gridcompfinalize ESMF_GridCompFinalize proc~esmf_gridcompfinalize->proc~esmf_compexecute proc~esmf_gridcompfinalizeact ESMF_GridCompFinalizeAct proc~esmf_gridcompfinalizeact->proc~esmf_compexecute proc~esmf_gridcompinitialize ESMF_GridCompInitialize proc~esmf_gridcompinitialize->proc~esmf_compexecute proc~esmf_gridcompinitializeact ESMF_GridCompInitializeAct proc~esmf_gridcompinitializeact->proc~esmf_compexecute proc~esmf_gridcompreadrestart ESMF_GridCompReadRestart proc~esmf_gridcompreadrestart->proc~esmf_compexecute proc~esmf_gridcomprun ESMF_GridCompRun proc~esmf_gridcomprun->proc~esmf_compexecute proc~esmf_gridcomprunact ESMF_GridCompRunAct proc~esmf_gridcomprunact->proc~esmf_compexecute proc~esmf_gridcompserviceloop ESMF_GridCompServiceLoop proc~esmf_gridcompserviceloop->proc~esmf_compexecute proc~esmf_gridcompwriterestart ESMF_GridCompWriteRestart proc~esmf_gridcompwriterestart->proc~esmf_compexecute proc~f_esmf_compexecute f_esmf_compexecute proc~f_esmf_compexecute->proc~esmf_compexecute

Source Code

  recursive subroutine ESMF_CompExecute(compp, method, &
    importState, exportState, clock, syncflag, phase, port, timeout, userRc, rc)
!
!
! !ARGUMENTS:
    type(ESMF_CompClass),    pointer                 :: compp
    type(ESMF_Method_Flag),  intent(in)              :: method
    type(ESMF_State),        intent(inout), optional :: importState
    type(ESMF_State),        intent(inout), optional :: exportState
    type(ESMF_Clock),        intent(in),    optional :: clock
    type(ESMF_Sync_Flag),    intent(in),    optional :: syncflag
    integer,                 intent(in),    optional :: phase
    integer,                 intent(in),    optional :: port
    integer,                 intent(in),    optional :: timeout
    integer,                 intent(out),   optional :: userRc
    integer,                 intent(out),   optional :: rc
!
! !DESCRIPTION:
! Component Execute method used by GridComp and CplComp for:
!   * Initialize,
!   * Run,
!   * Finalize,
!   * ReadRestart,
!   * WriteRestart.
!
! Call into the associated user code for a component's method.
!
! The arguments are:
! \begin{description}
!
! \item[compp]
!   Component to call Initialization routine for.
! \item[method]
!   One of the ESMF Component methods. See section \ref{const:methods} 
!   for a complete list of valid methods.
! \item[{[importState]}]  
!   Import data for component method.
! \item[{[exportState]}]  
!   Export data for component method.
! \item[{[clock]}]  
!   External clock for passing in time information.
! \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.
! \item[{[phase]}]
!   The phase of a multi-phase method. Default is 1.
! \item[{[port]}]
!   Port number. Only used for ESMF\_METHOD\_SERVICELOOP.
! \item[{[timeout]}]
!   Time out in seconds.
! \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}
!
!EOPI
!------------------------------------------------------------------------------
    integer                 :: localrc      ! local return code
    integer                 :: localUserRc  ! return code from user code
    type(ESMF_Sync_Flag)    :: blocking     ! local blocking flag
    type(ESMF_VM)           :: vm           ! VM for current context
    integer                 :: phaseArg
    integer                 :: portArg
    integer                 :: timeoutArg
    real(ESMF_KIND_R8)      :: usedTime
    character(160)          :: msgString
        
    ! dummys that will provide initializer values if args are not present
    type(ESMF_State)        :: dummyis, dummyes
    type(ESMF_Clock)        :: dummyclock
    type(ESMF_Status)       :: baseStatus

    ! Initialize return code; assume not implemented until success is certain
    localrc = ESMF_RC_NOT_IMPL
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
        
    ! Test incoming compp object
    if (.not.associated(compp)) then
      call ESMF_LogSetError(ESMF_RC_OBJ_BAD, &
        msg="Not a valid pointer to ESMF Component object", &
        ESMF_CONTEXT, rcToReturn=rc)
      return
    endif

    ! Check init status of arguments
    ESMF_INIT_CHECK_DEEP(ESMF_CompClassGetInit, compp, rc)

    call ESMF_BaseGetStatus(compp%base, baseStatus, rc=localrc)
    if (ESMF_LogFoundError(localrc, &
        ESMF_ERR_PASSTHRU, &
        ESMF_CONTEXT, rcToReturn=rc)) return
        
    if (baseStatus /= ESMF_STATUS_READY) then
      call ESMF_LogSetError(ESMF_RC_OBJ_BAD, &
        msg="uninitialized or destroyed Component object", &
        ESMF_CONTEXT, rcToReturn=rc) 
      return
    endif
    
    ! check if this is a supported combination of conditions
    if (compp%vm_released.and. &
      (method/=ESMF_METHOD_WAIT).and. &
      (method/=ESMF_METHOD_NONE)) then
      call ESMF_LogSetError(ESMF_RC_OBJ_BAD, &
        msg="cannot call this method while the component is executing", &
        ESMF_CONTEXT, rcToReturn=rc) 
      return
    endif

    ! set the default mode to ESMF_SYNC_VASBLOCKING
    if (present(syncflag)) then
      blocking = syncflag
    else
      blocking = ESMF_SYNC_VASBLOCKING
    endif
    
    ! supply default objects if unspecified by the caller
    if (present(importState)) then
      compp%is = importState
      compp%compStatus%isIsPresent = .true.
    else
      ! use dummy variable
      compp%is = dummyis
    endif

    if (present(exportState)) then
      compp%es = exportState
      compp%compStatus%esIsPresent = .true.
    else
      ! use dummy variable
      compp%es = dummyes
    endif

    ! and something for clocks?
    if (present(clock)) then
      compp%argclock = clock
    else
      ! use dummy variable -> set to null pointer since this is deep C++ impl.
      call ESMF_ClockSetThis(dummyclock, ESMF_NULL_POINTER, localrc)
      if (ESMF_LogFoundError(localrc, &
        ESMF_ERR_PASSTHRU, &
        ESMF_CONTEXT, rcToReturn=rc)) return
      compp%argclock = dummyclock
    endif

    ! set phase and port number
    phaseArg = 1 ! default phase
    if (present(phase)) phaseArg = phase
    
    if ((method==ESMF_METHOD_SERVICELOOP) .or. &
      (method==ESMF_METHOD_SERVICELOOPIC)) then
      ! deal with special phase/port argument combination
      if (phaseArg /= 1) then
        call ESMF_LogSetError(ESMF_RC_ARG_BAD, &
          msg="Phase must be 1 for ServiceLoop() call.", &
          ESMF_CONTEXT, rcToReturn=rc) 
        return
      endif
      if (present(port)) then
        if (port < 1024 .or. port > 65535) then
          call ESMF_LogSetError(ESMF_RC_ARG_BAD, &
            msg="The 'port' argument is outside valid range [1024, 65535]", &
            ESMF_CONTEXT, rcToReturn=rc)
          return
        endif
        portArg = port    ! valid port number
      else
        portArg = -1      ! indicate that no port was specified
      endif
    else
      ! all other component methods have regular phase arguments
      if (present(port)) then
        call ESMF_LogSetError(ESMF_RC_ARG_BAD, &
          msg="Port is only allowed for ServiceLoop() call.", &
          ESMF_CONTEXT, rcToReturn=rc) 
        return
      endif
      portArg = -1        ! indicate that no port was specified
    endif
    
    ! Timeout argument
    timeoutArg = 0; ! default timeout to flag issue if it is really used later
    if (present(timeout)) then
      if (timeout < 0) then
        call ESMF_LogSetError(ESMF_RC_ARG_BAD, &
          msg="The 'timeout' argument must be positive", &
          ESMF_CONTEXT, rcToReturn=rc)
        return
      endif
      timeoutArg = timeout    ! valid timeout
    endif

    ! Wrap comp so it's passed to C++ correctly.
    compp%compw%compp => compp
    ESMF_INIT_SET_CREATED(compp%compw)
    compp%compw%isNamedAlias = .false.

    ! Set up the arguments
    if (compp%iAmParticipant) then
      ! only call this on PETs that participate
      call c_ESMC_FTableSetStateArgs(compp%ftable, method, phaseArg, &
        compp%compw, compp%is, compp%es, compp%argclock, compp%compTunnel, &
        localrc)
      if (ESMF_LogFoundError(localrc, &
        ESMF_ERR_PASSTHRU, &
        ESMF_CONTEXT, rcToReturn=rc)) return
    endif
    
    localUserRc = ESMF_SUCCESS  ! initialize to success
    ! pass back the initialized value of userRc, just in case of a bail out
    if (present(userRc)) userRc = localUserRc
    
    ! All of the participating PETs must call in, but also non-participating
    ! PETs that hold a valid VM and show up here enter the callback mechanism.
    if (compp%iAmParticipant .or. compp%compStatus%vmIsPresent) then
      ! store the start time
      call ESMF_VMWtime(compp%startTime, rc=localrc)
      if (ESMF_LogFoundError(localrc, &
        ESMF_ERR_PASSTHRU, &
        ESMF_CONTEXT, rcToReturn=rc)) return
      ! callback into user code
#if 0
write (msgString,*) "ESMF_CompExecute(), calling c_ESMC_FTableCallEntryPointVM(): timeoutArg=",timeoutArg
call ESMF_LogWrite(msgString, ESMF_LOGMSG_DEBUG, rc=localrc)
#endif
      call c_ESMC_FTableCallEntryPointVM(compp%compw, compp%vm_parent, &
        compp%vmplan, compp%vm_info, compp%vm_cargo, compp%ftable, method, &
        phaseArg, portArg, timeoutArg, compp%vm_recursionCount, localrc)
      if (ESMF_LogFoundError(localrc, &
        ESMF_ERR_PASSTHRU, &
        ESMF_CONTEXT, rcToReturn=rc)) return
      ! For threaded VMs (single- or multi-threaded) the child VM will 
      ! now be running concurrently with the parent VM.
      ! Also for component tunnels, the actual component will now be executing
      ! concurrently with the dual component that came in to this call.

      ! wait for blocking modes
      if (blocking == ESMF_SYNC_VASBLOCKING .or. blocking == ESMF_SYNC_BLOCKING) then
        ! wait for all child PETs that run in this parent's PET VAS to finish
        ! determine how long the component has been released already
        call ESMF_VMWTime(usedTime, rc=localrc)
        if (ESMF_LogFoundError(localrc, &
          ESMF_ERR_PASSTHRU, &
          ESMF_CONTEXT, rcToReturn=rc)) return
        usedTime = usedTime - compp%startTime
        ! allow remaining time for timeout, but at least 1 second to wrap up
        timeoutArg = max(timeoutArg - int(usedTime), 1)
#if 0
write (msgString,*) "ESMF_CompExecute(), calling c_ESMC_CompWait(): usedTime=",usedTime,"timeoutArg=",timeoutArg
call ESMF_LogWrite(msgString, ESMF_LOGMSG_DEBUG, rc=localrc)
#endif
        call c_ESMC_CompWait(compp%vm_parent, compp%vmplan, compp%vm_info, &
          compp%vm_cargo, timeoutArg, compp%vm_recursionCount, localUserRc, &
          localrc)
        ! localUserRc - return code of registered user callback method
        ! localrc     - return code of ESMF internal callback stack
        if (ESMF_LogFoundError(localrc, &
          ESMF_ERR_PASSTHRU, &
          ESMF_CONTEXT, rcToReturn=rc)) return
      endif
    endif
      
    ! sync PETs according to blocking mode
    if (blocking == ESMF_SYNC_NONBLOCKING) then
      compp%vm_released = .true.
    else
      compp%vm_released = .false.       ! indicate child VM has been caught
      ! for ESMF_SYNC_BLOCKING _all_ parent PETs will be synced on exit
      if (blocking == ESMF_SYNC_BLOCKING) then
        ! the current context _is_ the parent context...
        call ESMF_VMGetCurrent(vm=vm, rc=localrc)  ! determine current VM
        if (ESMF_LogFoundError(localrc, &
          ESMF_ERR_PASSTHRU, &
          ESMF_CONTEXT, rcToReturn=rc)) return
        call ESMF_VMBarrier(vm=vm, rc=localrc) ! barrier across parent VM
        if (ESMF_LogFoundError(localrc, &
          ESMF_ERR_PASSTHRU, &
          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_CompExecute