ESMF_ReconcileZapProxies Subroutine

private subroutine ESMF_ReconcileZapProxies(state, rc)

Arguments

Type IntentOptional Attributes Name
type(ESMF_State), intent(inout) :: state
integer, intent(out), optional :: rc

Source Code

    subroutine ESMF_ReconcileZapProxies(state, rc)
!
! !ARGUMENTS:
      type(ESMF_State), intent(inout)         :: state
      integer,          intent(out), optional :: rc
!
! !DESCRIPTION:
!     Proxy objects are identified and removed from the State. Information about
!   the zapped proxies is kept in the State for later handling during the
!   companion method ESMF_ReconcileZappedProxies().
!
!     The arguments are:
!     \begin{description}
!     \item[state]
!       The State from which to zap proxies.
!     \item[{[rc]}]
!       Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
!     \end{description}
!
!EOPI
      integer                             :: localrc, i
      type(ESMF_StateClass),      pointer :: stypep
      type(ESMF_StateItemWrap),   pointer :: itemList(:)
      character(len=ESMF_MAXSTR)          :: thisname
      type(ESMF_FieldType),       pointer :: fieldp
      type(ESMF_FieldBundleType), pointer :: fbpthis
      character(len=80)                   :: msgString

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

      stypep => state%statep

#ifdef RECONCILE_ZAP_LOG_on
      call ESMF_VMLogGarbageInfo(prefix="ZapProxies bef: ", &
        logMsgFlag=ESMF_LOGMSG_DEBUG, rc=localrc)
#endif

      itemList => null ()
      call ESMF_ContainerGet(container=stypep%stateContainer, itemList=itemList, &
        rc=localrc)
      if (ESMF_LogFoundError(localrc, &
        ESMF_ERR_PASSTHRU, &
        ESMF_CONTEXT, rcToReturn=rc)) return

      stypep%zapFlag => null()
          
      if (associated(itemList)) then
        allocate(stypep%zapFlag(size(itemList)))
        stypep%zapFlag = .false.
        ! Zap all proxies
        do i=1, size(itemList)
          ! First ensure the proxyFlag for the current object in the local
          ! State is set correctly. Each object internally (in Base) knows
          ! if it was created as a proxy or not. However, the local State
          ! might not correctly track this if the proxy object was created
          ! under a different State and then copied over into this State.
          ! This can happen e.g. under NUOPC when Fields or FieldBuindles
          ! from a smaller VM are shared with a larger VM. Then on the extra
          ! PETs the sharing protocol creates proxies using a temporary State
          ! which then are copied into the actual import/exportState seen in
          ! a later Reconcile.
          ! The only use cases are Field and FieldBundle objects under State.
          if (itemList(i)%si%otype==ESMF_STATEITEM_FIELD) then
            fieldp => itemList(i)%si%datap%fp%ftypep
            call ESMF_StateItemGet(itemList(i)%si, name=thisname, rc=localrc)
            if (ESMF_LogFoundError(localrc, &
              ESMF_ERR_PASSTHRU, &
              ESMF_CONTEXT, rcToReturn=rc)) return

#ifdef RECONCILE_ZAP_LOG_on
write(msgString,*) "ESMF_ReconcileZapProxies Field: "//trim(thisname), &
  itemList(i)%si%proxyFlag
call ESMF_LogWrite(msgString, ESMF_LOGMSG_DEBUG, rc=localrc)
#endif

            ! determine proxyFlag from Base level
            itemList(i)%si%proxyFlag = ESMF_IsProxy(fieldp%base, rc=localrc)
            if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
              ESMF_CONTEXT,  &
              rcToReturn=rc)) return

#ifdef RECONCILE_ZAP_LOG_on
write(msgString,*) "ESMF_ReconcileZapProxies Field: "//trim(thisname), &
  itemList(i)%si%proxyFlag
call ESMF_LogWrite(msgString, ESMF_LOGMSG_DEBUG, rc=localrc)
#endif

          else if (itemList(i)%si%otype==ESMF_STATEITEM_FIELDBUNDLE) then
            fbpthis => itemList(i)%si%datap%fbp%this
            call ESMF_StateItemGet(itemList(i)%si, name=thisname, rc=localrc)
            if (ESMF_LogFoundError(localrc, &
              ESMF_ERR_PASSTHRU, &
              ESMF_CONTEXT, rcToReturn=rc)) return

#ifdef RECONCILE_ZAP_LOG_on
write(msgString,*) "ESMF_ReconcileZapProxies Field: "//trim(thisname), &
  itemList(i)%si%proxyFlag
call ESMF_LogWrite(msgString, ESMF_LOGMSG_DEBUG, rc=localrc)
#endif

            ! determine proxyFlag from Base level
            itemList(i)%si%proxyFlag = ESMF_IsProxy(fbpthis%base, rc=localrc)
            if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
              ESMF_CONTEXT,  &
              rcToReturn=rc)) return

#ifdef RECONCILE_ZAP_LOG_on
write(msgString,*) "ESMF_ReconcileZapProxies Field: "//trim(thisname), &
  itemList(i)%si%proxyFlag
call ESMF_LogWrite(msgString, ESMF_LOGMSG_DEBUG, rc=localrc)
#endif

          endif
          ! Now the local State proxyFlag is consistent and can be used to
          ! determine whether the current object needs to be zapped or not.
          if (itemList(i)%si%proxyFlag) then
            stypep%zapFlag(i) = .true.  ! keep record about zapping
            call ESMF_StateItemGet(itemList(i)%si, name=thisname, rc=localrc)
            if (ESMF_LogFoundError(localrc, &
              ESMF_ERR_PASSTHRU, &
              ESMF_CONTEXT, rcToReturn=rc)) return
            ! Remove proxy object from state using its name. This is safe b/c
            ! a state only allows items with unique names.
            call ESMF_StateRemove (state, itemNameList=(/thisname/), rc=localrc)
            if (ESMF_LogFoundError(localrc, &
              ESMF_ERR_PASSTHRU, &
              ESMF_CONTEXT, rcToReturn=rc)) return
          end if
        end do
      endif

      stypep%zapList => itemList ! hang on for ESMF_ReconcileZappedProxies()

#ifdef RECONCILE_ZAP_LOG_on
      call ESMF_VMLogGarbageInfo(prefix="ZapProxies aft: ", &
        logMsgFlag=ESMF_LOGMSG_DEBUG, rc=localrc)
#endif

      if (present(rc)) rc = ESMF_SUCCESS
    end subroutine ESMF_ReconcileZapProxies