subroutine ESMF_StateReconcileIsNoop(state, vm, isNoop, rc)
!
! !ARGUMENTS:
type (ESMF_State), intent(inout) :: state
type (ESMF_VM), intent(in) :: vm
logical, intent(out) :: isNoop
integer, intent(out) :: rc
!
! !DESCRIPTION:
!
! Determine whether there is a need for reconciliation of {\tt state} across
! the PETs of {\tt vm}.
!
! The arguments are:
! \begin{description}
! \item[state]
! {\tt ESMF\_State} to be reconciled.
! \item[vm]
! The current {\tt ESMF\_VM} (virtual machine).
! \item[isNoop]
! Return {\tt .true.} if no reconcile is needed, {\tt .false.} otherwise.
! \item[{[rc]}]
! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!EOPI
integer :: localrc
type(ESMF_VMId) :: vmId
logical :: isNoopLoc
integer :: isNoopLocInt(1), isNoopInt(1)
logical, parameter :: profile = .false.
localrc = ESMF_RC_NOT_IMPL
isNoop = .false. ! assume reconcile is needed
call ESMF_VMGetVMId(vm, vmId=vmId, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, &
rcToReturn=rc)) return
if (profile) then
call ESMF_TraceRegionEnter("StateReconcileIsNoopLoc", rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, &
rcToReturn=rc)) return
endif
call StateReconcileIsNoopLoc(state, isNoopLoc=isNoopLoc, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, &
rcToReturn=rc)) return
if (profile) then
call ESMF_TraceRegionExit("StateReconcileIsNoopLoc", rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, &
rcToReturn=rc)) return
endif
isNoopLocInt(1) = 0
if (isNoopLoc) isNoopLocInt(1) = 1
if (profile) then
call ESMF_TraceRegionEnter("ESMF_VMAllReduce", rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, &
rcToReturn=rc)) return
endif
! logical AND reduction, only 1 if all incoming 1
call ESMF_VMAllReduce(vm, isNoopLocInt, isNoopInt, 1, ESMF_REDUCE_MIN, &
rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, &
rcToReturn=rc)) return
if (profile) then
call ESMF_TraceRegionExit("ESMF_VMAllReduce", rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, &
rcToReturn=rc)) return
endif
isNoop = (isNoopInt(1)==1) ! globally consistent result
! return successfully
rc = ESMF_SUCCESS
contains
recursive subroutine StateReconcileIsNoopLoc(stateR, isNoopLoc, rc)
type(ESMF_State), intent(in) :: stateR
logical, intent(out) :: isNoopLoc
integer, intent(out) :: rc
! - local variables
integer :: localrc
integer :: itemCount, item, fieldCount, arrayCount, i
character(ESMF_MAXSTR), allocatable :: itemNameList(:)
type(ESMF_StateItem_Flag), allocatable :: itemTypeList(:)
type(ESMF_State) :: nestedState
type(ESMF_Field) :: field
type(ESMF_FieldBundle) :: fieldbundle
type(ESMF_Array) :: array
type(ESMF_ArrayBundle) :: arraybundle
type(ESMF_RouteHandle) :: routehandle
type(ESMF_VM) :: vmItem
type(ESMF_VMId) :: vmIdItem
type(ESMF_Pointer) :: thisItem
logical :: isFlag
localrc = ESMF_RC_NOT_IMPL
isNoopLoc = .true.
! query
call ESMF_StateGet(stateR, itemCount=itemCount, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, &
rcToReturn=rc)) return
if (itemCount > 0) then
allocate(itemNameList(itemCount))
allocate(itemTypeList(itemCount))
call ESMF_StateGet(stateR, itemNameList=itemNameList, &
itemtypeList=itemtypeList, rc=localrc)
if (ESMF_LogFoundError(localrc, &
ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
do item=1, itemCount
! access the VM of the item, using appropriate API
if ((itemtypeList(item) == ESMF_STATEITEM_STATE)) then
call ESMF_StateGet(stateR, itemName=itemNameList(item), &
nestedState=nestedState, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, &
rcToReturn=rc)) return
call ESMF_StateGet(nestedState, vm=vmItem, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, &
rcToReturn=rc)) return
else if (itemtypeList(item) == ESMF_STATEITEM_FIELD) then
call ESMF_StateGet(stateR, itemName=itemNameList(item), &
field=field, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, &
rcToReturn=rc)) return
call ESMF_FieldGet(field, vm=vmItem, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, &
rcToReturn=rc)) return
else if (itemtypeList(item) == ESMF_STATEITEM_FIELDBUNDLE) then
call ESMF_StateGet(stateR, itemName=itemNameList(item), &
fieldbundle=fieldbundle, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, &
rcToReturn=rc)) return
call ESMF_FieldBundleGet(fieldbundle, vm=vmItem, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, &
rcToReturn=rc)) return
else if (itemtypeList(item) == ESMF_STATEITEM_ARRAY) then
call ESMF_StateGet(stateR, itemName=itemNameList(item), &
array=array, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, &
rcToReturn=rc)) return
call ESMF_ArrayGet(array, vm=vmItem, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, &
rcToReturn=rc)) return
else if (itemtypeList(item) == ESMF_STATEITEM_ARRAYBUNDLE) then
call ESMF_StateGet(stateR, itemName=itemNameList(item), &
arraybundle=arraybundle, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, &
rcToReturn=rc)) return
call ESMF_ArrayBundleGet(arraybundle, vm=vmItem, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, &
rcToReturn=rc)) return
else if (itemtypeList(item) == ESMF_STATEITEM_ROUTEHANDLE) then
call ESMF_StateGet(stateR, itemName=itemNameList(item), &
routehandle=routehandle, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, &
rcToReturn=rc)) return
call ESMF_RouteHandleGet(routehandle, vm=vmItem, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, &
rcToReturn=rc)) return
endif
#if 0
call ESMF_LogWrite("processing "//trim(itemNameList(item)), ESMF_LOGMSG_DEBUG, rc=localrc)
#endif
call ESMF_VMGetThis(vmItem, thisItem, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, &
rcToReturn=rc)) return
if (thisItem == ESMF_NULL_POINTER) isNoopLoc = .false. ! found proxy
! exit for .false. already from proxy
if (.not.isNoopLoc) exit
call ESMF_VMGetVMId(vmItem, vmId=vmIdItem, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, &
rcToReturn=rc)) return
isNoopLoc = ESMF_VMIdCompare(vmIdItem, vmId, keyOnly=.true., &
rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, &
rcToReturn=rc)) return
#if 0
block
character(160) :: msgStr
call ESMF_VMIdLog(vmIdItem, prefix="vmIdItem: ", rc=localrc)
write(msgStr,*) "isNoopLoc: ", isNoopLoc
call ESMF_LogWrite(msgStr, ESMF_LOGMSG_DEBUG, rc=localrc)
end block
#endif
if (.not.isNoopLoc) exit ! exit for .false.
vmId = vmIdItem ! more likely to hit pointer comparison this way
enddo
deallocate(itemNameList)
deallocate(itemTypeList)
endif
end subroutine StateReconcileIsNoopLoc
end subroutine ESMF_StateReconcileIsNoop