diff --git a/src/Infrastructure/VM/include/ESMCI_VM.h b/src/Infrastructure/VM/include/ESMCI_VM.h index 5a6493d332..8fdb37aa54 100644 --- a/src/Infrastructure/VM/include/ESMCI_VM.h +++ b/src/Infrastructure/VM/include/ESMCI_VM.h @@ -81,7 +81,7 @@ class VMId { namespace ESMCI { // ESMCI::VMId methods: -bool VMIdCompare(const VMId *vmID1, const VMId *vmID2); +bool VMIdCompare(const VMId *vmID1, const VMId *vmID2, bool keyOnly=false); bool VMIdLessThan(const VMId *vmID1, const VMId *vmID2); int VMIdCopy(VMId *vmIDdst, VMId *vmIDsrc); } // namespace ESMCI diff --git a/src/Infrastructure/VM/interface/ESMCI_VM_F.C b/src/Infrastructure/VM/interface/ESMCI_VM_F.C index 760c8fbe60..ff9f1fea75 100644 --- a/src/Infrastructure/VM/interface/ESMCI_VM_F.C +++ b/src/Infrastructure/VM/interface/ESMCI_VM_F.C @@ -1660,7 +1660,7 @@ extern "C" { } void FTN_X(c_esmc_vmidcompare)(ESMCI::VMId **vmid1, ESMCI::VMId **vmid2, - ESMC_Logical *result, int *rc){ + ESMC_Logical *keyOnly, ESMC_Logical *result, int *rc){ #undef ESMC_METHOD #define ESMC_METHOD "c_esmc_vmidcompare()" // Initialize return code; assume routine not implemented @@ -1669,7 +1669,10 @@ extern "C" { ESMCI_NULL_CHECK_PRC(vmid1, rc) ESMCI_NULL_CHECK_PRC(vmid2, rc) ESMCI_NULL_CHECK_PRC(result, rc) - bool resultBool = ESMCI::VMIdCompare(*vmid1, *vmid2); + bool keyOnlyOpt = false; // default + if (ESMC_NOT_PRESENT_FILTER(keyOnly) != ESMC_NULL_POINTER) + if (*keyOnly == ESMF_TRUE) keyOnlyOpt = true; + bool resultBool = ESMCI::VMIdCompare(*vmid1, *vmid2, keyOnlyOpt); *result = resultBool ? ESMF_TRUE : ESMF_FALSE; // return successfully if (rc!=NULL) *rc = ESMF_SUCCESS; diff --git a/src/Infrastructure/VM/interface/ESMF_VM.F90 b/src/Infrastructure/VM/interface/ESMF_VM.F90 index 5ceae6c30e..c41955b510 100644 --- a/src/Infrastructure/VM/interface/ESMF_VM.F90 +++ b/src/Infrastructure/VM/interface/ESMF_VM.F90 @@ -10353,7 +10353,7 @@ end subroutine ESMF_VMPlanMinThreads ! !IROUTINE: ESMF_VMIdCompare - Compare two ESMF_VMId objects ! !INTERFACE: - function ESMF_VMIdCompare(vmId1, vmId2, rc) + function ESMF_VMIdCompare(vmId1, vmId2, keyOnly, rc) ! ! !RETURN VALUE: logical :: ESMF_VMIdCompare @@ -10361,6 +10361,7 @@ function ESMF_VMIdCompare(vmId1, vmId2, rc) ! !ARGUMENTS: type(ESMF_VMId), intent(in) :: vmId1 type(ESMF_VMId), intent(in) :: vmId2 + logical, intent(in), optional :: keyOnly integer, intent(out), optional :: rc ! ! !DESCRIPTION: @@ -10372,6 +10373,9 @@ function ESMF_VMIdCompare(vmId1, vmId2, rc) ! ESMF_VMId object 1 ! \item[vmId2] ! ESMF_VMId object 2 +! \item[{[keyOnly]}] +! For {\tt .true.} only compare the vmKey parts. Default is +! {\tt .false.}. ! \item[{[rc]}] ! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors. ! \end{description} @@ -10379,14 +10383,19 @@ function ESMF_VMIdCompare(vmId1, vmId2, rc) !EOPI !------------------------------------------------------------------------------ integer :: localrc ! local return code - type(ESMF_Logical) :: tf + type(ESMF_Logical) :: tf, keyOnlyOpt ! initialize return code; assume routine not implemented localrc = ESMF_RC_NOT_IMPL if (present(rc)) rc = ESMF_RC_NOT_IMPL + keyOnlyOpt = ESMF_FALSE + if (present(keyOnly)) then + if (keyOnly) keyOnlyOpt = ESMF_TRUE + endif + ! Call into the C++ interface - call c_ESMC_VMIdCompare(vmId1, vmId2, tf, localrc) + call c_ESMC_VMIdCompare(vmId1, vmId2, keyOnly, tf, localrc) ESMF_VMIdCompare = tf == ESMF_TRUE if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & ESMF_CONTEXT, rcToReturn=rc)) return diff --git a/src/Infrastructure/VM/src/ESMCI_VM.C b/src/Infrastructure/VM/src/ESMCI_VM.C index fd341a86a9..db32a1532f 100644 --- a/src/Infrastructure/VM/src/ESMCI_VM.C +++ b/src/Infrastructure/VM/src/ESMCI_VM.C @@ -729,11 +729,13 @@ bool VMIdCompare( // !ARGUMENTS: // const VMId *vmID1, - const VMId *vmID2 + const VMId *vmID2, + bool keyOnly ){ // // !DESCRIPTION: -// Compare two {\tt ESMC\_VMId} objects. +// Compare two {\tt ESMC\_VMId} objects. If {\tt keyOnly==true} only compare +// vmKey part. // //EOPI //----------------------------------------------------------------------------- @@ -742,8 +744,10 @@ bool VMIdCompare( "- Invalid vmIDs", ESMC_CONTEXT, NULL); return false; // bail out } - if (vmID1->localID != vmID2->localID){ - return false; + if (!keyOnly){ + if (vmID1->localID != vmID2->localID){ + return false; + } } return VMKeyCompare(vmID1->vmKey, vmID2->vmKey); } diff --git a/src/Superstructure/StateReconcile/src/ESMF_StateReconcile.F90 b/src/Superstructure/StateReconcile/src/ESMF_StateReconcile.F90 index 644933913d..0e6a006379 100644 --- a/src/Superstructure/StateReconcile/src/ESMF_StateReconcile.F90 +++ b/src/Superstructure/StateReconcile/src/ESMF_StateReconcile.F90 @@ -219,6 +219,13 @@ subroutine ESMF_StateReconcile(state, vm, rc) rcToReturn=rc)) return endif + if (isNoop) then +call ESMF_LogWrite("returning early with isNoop=.true.", ESMF_LOGMSG_DEBUG, rc=localrc) + ! successful early return because of NOOP condition + if (present(rc)) rc = ESMF_SUCCESS + return + endif + ! Each PET broadcasts the object ID lists and compares them to what ! they get back. Missing objects are sent so they can be recreated ! on the PETs without those objects as "proxy" objects. Eventually @@ -322,6 +329,7 @@ subroutine ESMF_StateReconcileIsNoop(state, vm, isNoop, rc) integer :: localrc type(ESMF_VMId) :: vmId logical :: isNoopLoc + integer :: isNoopLocInt(1), isNoopInt(1) localrc = ESMF_RC_NOT_IMPL @@ -331,15 +339,21 @@ subroutine ESMF_StateReconcileIsNoop(state, vm, isNoop, rc) if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, & rcToReturn=rc)) return - call ESMF_VMIdLog(vmId, prefix="ESMF_StateReconcileIsNoop(): ", & - rc=localrc) + call StateReconcileIsNoopLoc(state, isNoopLoc=isNoopLoc, rc=localrc) if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, & rcToReturn=rc)) return - call StateReconcileIsNoopLoc(state, isNoopLoc=isNoopLoc, rc=localrc) + isNoopLocInt(1) = 0 + if (isNoopLoc) isNoopLocInt(1) = 1 + + ! 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 (isNoopInt(1)==1) isNoop = .true. ! found that Reconcile is a NOOP + ! return successfully rc = ESMF_SUCCESS @@ -362,10 +376,11 @@ recursive subroutine StateReconcileIsNoopLoc(stateR, isNoopLoc, rc) type(ESMF_RouteHandle) :: routehandle type(ESMF_VM) :: vmItem type(ESMF_VMId) :: vmIdItem + type(ESMF_Pointer) :: thisItem localrc = ESMF_RC_NOT_IMPL - isNoopLoc = .false. ! assume reconcile needed until found otherwise + isNoopLoc = .true. ! query call ESMF_StateGet(stateR, itemCount=itemCount, rc=localrc) @@ -454,14 +469,24 @@ recursive subroutine StateReconcileIsNoopLoc(stateR, isNoopLoc, rc) ESMF_CONTEXT, rcToReturn=rc)) return endif - call ESMF_VMGetVMId(vmItem, vmId=vmIdItem, rc=localrc) - if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, & - rcToReturn=rc)) return + call ESMF_VMGetThis(vmItem, thisItem, rc=localrc) + if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, & + rcToReturn=rc)) return - call ESMF_VMIdLog(vmIdItem, prefix="vmIdItem: ", & - rc=localrc) - if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, & - rcToReturn=rc)) return + if (thisItem == ESMF_NULL_POINTER) isNoopLoc = .false. ! found proxy + + if (.not.isNoopLoc) exit ! exit for .false. already recurse or proxy + + 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 (.not.isNoopLoc) exit ! exit for .false. enddo