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