From 84457af16b6e157e5efc09e13fb7eed2e0ce6e89 Mon Sep 17 00:00:00 2001 From: Fei Liu Date: Thu, 17 Jun 2021 11:39:34 -0400 Subject: [PATCH 01/32] updated checkRingTime --- .../TimeMgr/include/ESMCI_Alarm.h | 4 + src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C | 343 ++---------------- .../TimeMgr/tests/ESMF_AlarmUTest.F90 | 2 +- 3 files changed, 45 insertions(+), 304 deletions(-) diff --git a/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h b/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h index 4df1bc1b51..93b5476cc6 100644 --- a/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h +++ b/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h @@ -139,6 +139,7 @@ class Alarm { // to adjust alarm on timeStep // direction (sign) change bool enabled; // able to ring (TMG 4.5.3) + bool ringerIsOn; // whether ringer is on or off bool sticky; // must be turned off via // Alarm::ringerOff(), // otherwise will turn self off after @@ -272,6 +273,9 @@ class Alarm { // reconstruct ringBegin during ESMF_DIRECTION_REVERSE int resetRingBegin(bool timeStepPositive); + // enable Sticky + void enableSticky(void); + // friend class alarm friend class Clock; diff --git a/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C b/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C index 2143e19c7e..bdc4d020c7 100644 --- a/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C +++ b/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C @@ -146,7 +146,10 @@ int Alarm::count=0; alarm->ringTime = clock->currTime + alarm->ringInterval; alarm->prevRingTime = alarm->firstRingTime = alarm->ringTime; } + }else{ + alarm->ringInterval = clock->timeStep; } + if (stopTime != ESMC_NULL_POINTER) { alarm->stopTime = *stopTime; } @@ -169,6 +172,7 @@ int Alarm::count=0; if (sticky != ESMC_NULL_POINTER) { alarm->sticky = *sticky; } + alarm->ringerIsOn = true; // TODO: invoke private method, shared with Alarm::set(), to calculate // first ringTime for interval alarms, given ringInterval and none, @@ -417,6 +421,7 @@ int Alarm::count=0; } if (sticky != ESMC_NULL_POINTER) { this->sticky = *sticky; + if(*sticky) enableSticky(); } // TODO: invoke private method, shared with ESMCI_alarmCreate(), to @@ -438,6 +443,12 @@ int Alarm::count=0; } // end Alarm::set +void Alarm::enableSticky(void){ + // 1/100th of a second granuality to ensure integer return when being divided by + //this->ringInterval=TimeInterval(0, 1, 100, 0, 0, 0); + this->ringInterval=TimeInterval(1, 0, 1, 0, 0, 0); +} + //------------------------------------------------------------------------- //BOP // !IROUTINE: Alarm::get - Gets an alarm's properties @@ -712,6 +723,7 @@ int Alarm::count=0; return(ESMF_FAILURE); } + ringerIsOn = true; ringing = true; rc = ESMF_SUCCESS; @@ -752,6 +764,7 @@ int Alarm::count=0; // turn alarm off ringing = false; + ringerIsOn = false; timeStepRingingCount = 0; if (clock->direction == ESMF_DIRECTION_FORWARD) { @@ -800,7 +813,7 @@ int Alarm::count=0; // bool is ringing or not // // !ARGUMENTS: - int *rc) const { // out - error return code + int *rc) const { // out - error return code // // !DESCRIPTION: // Checks if {\tt ESMC\_Alarm}'s ringing state is set. @@ -1113,318 +1126,42 @@ int Alarm::count=0; // must be associated with a clock if(clock == ESMC_NULL_POINTER) { char logMsg[ESMF_MAXSTR]; - sprintf(logMsg, "alarm %s is not associated with any clock.", name); + sprintf(logMsg, "newalarm %s is not associated with any clock.", name); ESMC_LogDefault.Write(logMsg, ESMC_LOGMSG_WARN,ESMC_CONTEXT); return(false); } - // get clock's timestep direction: positive or negative - bool positive = (clock->currAdvanceTimeStep.absValue() == - clock->currAdvanceTimeStep) ? true : false; - - if (clock->direction == ESMF_DIRECTION_FORWARD) { - - // carry previous flag forward - ringingOnPrevTimeStep = ringingOnCurrTimeStep; - - // perform pre-checks first ... - - if (enabled) { - if (userChangedRingInterval) { - // check that user's new ringInterval is same sign as timeStep - TimeInterval zeroTimeStep; - if ((ringInterval > zeroTimeStep && - clock->currAdvanceTimeStep < zeroTimeStep) || - (ringInterval < zeroTimeStep && - clock->currAdvanceTimeStep > zeroTimeStep) ) { - ESMC_LogDefault.MsgFoundError(ESMC_RC_VAL_WRONG, - "; user changed alarm ringInterval, " - "which is not same sign as clock timeStep.", ESMC_CONTEXT, rc); - return(false); - } - } - if (userChangedRingTime) { - // check that user's new ringTime is within ringable range - if (positive ? clock->currTime > ringTime : - clock->currTime < ringTime) { - ESMC_LogDefault.MsgFoundError(ESMC_RC_VAL_OUTOFRANGE, - "; user changed alarm ringTime, " - "which is not within clock ringable range", ESMC_CONTEXT, rc); - return(false); - } - } - // if clock timeStep sign changed, adjust ringInterval accordingly - TimeInterval zeroTimeStep; - bool userChangedTimeStepSign = - ( (clock->currAdvanceTimeStep < zeroTimeStep && - clock->prevAdvanceTimeStep > zeroTimeStep) || - (clock->currAdvanceTimeStep > zeroTimeStep && - clock->prevAdvanceTimeStep < zeroTimeStep) ); - if (userChangedTimeStepSign) { - if (!userChangedRingInterval) { - // change sign to match clock timeStep - ringInterval *= -1; - ringDuration *= -1; - } - } - // if either clock timeStep sign changed or clock direction mode - // changed, pull back ringTime into ringable range - if (userChangedTimeStepSign || clock->userChangedDirection) { - if (!userChangedRingTime) { - bool stopTimeEnabled = - stopTime.Time::validate("initialized") == ESMF_SUCCESS; - while (positive ? clock->prevTime >= ringTime : - clock->prevTime <= ringTime) { - // check if ringing stopTime limit reached, TODO: test - if (stopTimeEnabled) { - if (positive ? ringTime >= (stopTime - ringInterval) : - ringTime <= (stopTime - ringInterval) ) break; - } - // otherwise increment it - prevRingTime = ringTime; - ringTime += ringInterval; - } - } - } - // done processing changed flags, reset if necessary - if (userChangedRingTime) userChangedRingTime = false; - if (userChangedRingInterval) userChangedRingInterval = false; - if (clock->userChangedDirection) clock->userChangedDirection = false; - } - - // ... then check if time to turn on alarm - if (!ringing && enabled) - Alarm::checkTurnOn(positive); - - // else if not sticky, check if time to turn off alarm - // (user is responsible for turning off sticky alarms via RingerOff()) - // TODO: maybe should not be else clause, just an "if" on its own, since - // ringTimeStepCount=0 would imply turning off in the same timeStep? But - // would need to move timeStepRingingCount++ up. - else if (!sticky && ringing && enabled) { - - // first check if next alarm time has been reached, - // then check if time to turn off alarm. - if (!Alarm::checkTurnOn(positive)) { - TimeInterval zeroTimeInterval(0,0,1,0,0,0); - if (ringTimeStepCount == 1 && - ringDuration != zeroTimeInterval) { // use ringDuration ... - TimeInterval cumulativeRinging; - cumulativeRinging = clock->currTime - ringBegin; - if (cumulativeRinging.TimeInterval::absValue() >= - ringDuration.TimeInterval::absValue()) { - ringingOnCurrTimeStep = ringing = false; - timeStepRingingCount = 0; - } - // ... otherwise use ringTimeStepCount - } else if (ringTimeStepCount >= 1) { - if (timeStepRingingCount >= ringTimeStepCount) { - ringingOnCurrTimeStep = ringing = false; - timeStepRingingCount = 0; - } - } // TODO: else error, ringTimeStepCount <= 0 (ringing counter is - // always positive) Validate() ? - } - } - - // count for how many clock time steps the alarm is ringing - if (ringing) timeStepRingingCount++; - - // ensure a sticky repeatable alarm's ringTime remains in ringable range, - // in case it is not turned off for a while, or if - // clock->timeStep >= ringInterval - TimeInterval zeroTimeInterval(0,0,1,0,0,0); - if (sticky && ringInterval != zeroTimeInterval && - clock->advanceCount != 0) { - //printf("ringTime before:\n"); - //print("ringTime string"); - bool stopTimeEnabled = - stopTime.Time::validate("initialized") == ESMF_SUCCESS; - // works for positive and negative ringIntervals TODO: test negative - while (positive ? clock->currTime >= ringTime : - clock->currTime <= ringTime) { - // check if ringing stopTime limit reached, TODO: test - if (stopTimeEnabled) { - if (positive ? ringTime >= (stopTime - ringInterval) : - ringTime <= (stopTime - ringInterval) ) break; - } - // otherwise increment it - prevRingTime = ringTime; - ringTime += ringInterval; - // TODO: if in practice, users use a timeStep which is much, much - // greater than ringInterval, then a single-step calculated - // approach to updating the ringTime, rather than a loop - // approach, may be more efficient. - } - //printf("ringTime after:\n"); - //print("ringTime string"); - } - - } else { // ESMF_DIRECTION_REVERSE - - // TODO: Make more robust by removing the following simplifying - // assumptions: - // - // 1) timeSteps are constant throughout clock run (including sign). - // 2) ringInterval, ringDuration are constant throughout clock run. - // 3) sticky alarms must have traversed through at least one alarm - // (to save the ringEnd time) in order to reverse. For - // repeating sticky alarms, previous ringEnds are assumed to be - // equally spaced by a constant ringInterval. - // - // The solution will involve saving clock and alarm state at every - // timeStep, which means dynamically allocated stacks (stacks of - // clock and alarm objects). These stacks can be - // initially sized at Create() time, then reallocated as necessary - // (upon those advance() calls which would require more space). - // Will need flag upon Create() for user to hint at need for - // this extra overhead for reversible clocks and alarms. - - // Note: Sticky alarms need to have been traversed forward in order - // to be reversed (to save ringEnd upon user RingerOff() event). - // In contrast, non-sticky alarms can be reversed without first - // having been traversed forward. This implies that the logic - // cannot use prev* state variables in order to step back; all - // state variables must be reconstructed from timeStep, - // ringInterval, and ringDuration. Hence the use of ringTimeEnd - // below. - - // if sticky alarm, must have traversed forward far enough to have - // called RingerOff(), causing the ringEnd time to be saved. - if(sticky && ringEnd.Time::validate("initialized") != ESMF_SUCCESS) { - char logMsg[ESMF_MAXSTR]; - sprintf(logMsg, "Sticky alarm %s cannot be reversed since it has " - "not been traversed forward and turned off via " - "a user call to ESMF_AlarmRingerOff(), thereby " - "enabling Time Manager to know the time to turn it " - "back on in reverse.", name); - ESMC_LogDefault.Write(logMsg, ESMC_LOGMSG_WARN,ESMC_CONTEXT); - return(false); - } - - // adjust ring state variables if needed - // (pull back ringTime, etc. into ringable range if necessary) - - // ... adjust if sticky alarm ... - if (sticky) { - while ( ((positive && ringEnd > clock->currTime) || - (!positive && ringEnd < clock->currTime)) && - (ringTime != firstRingTime)) { - ringEnd -= ringInterval; - ringTime = prevRingTime; - prevRingTime -= ringInterval; - } - } - // ... or non-sticky alarm, if user just changed clock direction to - // REVERSE ... - if (clock->userChangedDirection) { - clock->userChangedDirection = false; // reset changed flag - if (!sticky) { - if (((positive && ringTime > (clock->currTime + clock->timeStep)) || - (!positive && ringTime < (clock->currTime + clock->timeStep))) && - (ringTime != firstRingTime)) { - ringTime = prevRingTime; - prevRingTime -= ringInterval; - Alarm::resetRingBegin(positive); - } - } - } - - // ... then determine when alarm ended ringing in forward mode ... - Time ringTimeEnd; - if (enabled) { - if (sticky) { - ringTimeEnd = ringEnd; - } else { // non-sticky - TimeInterval zeroTimeInterval(0,0,1,0,0,0); - if (ringTimeStepCount == 1 && - ringDuration != zeroTimeInterval) { // use ringDuration ... - ringTimeEnd = ringBegin + ringDuration; - // ... otherwise use ringTimeStepCount - } else if (ringTimeStepCount >= 1) { - // If ringBegin hasn't been initialized, set ringBegin to clock's startTime - if(ringBegin.getCalendar() == NULL){ - ringBegin = clock->startTime; - } - ringTimeEnd = ringBegin + ringTimeStepCount * clock->timeStep; - } // TODO: else error, ringTimeStepCount <= 0 (ringing counter is - // always positive) Validate() ? - } - } +#define DEBUG 1 + // If the alarm is sticky then whether it's ringing or not is controled + // by ringerOn or ringerOff by user - // ... and use it to check if time to turn alarm back *on* in reverse mode - if (!ringing && enabled) { - if (sticky) { - ringingOnCurrTimeStep = ringing = (clock->currTime == ringTimeEnd); - } else { - ringingOnCurrTimeStep = ringing = (positive) ? - (clock->currTime < ringTimeEnd) && - (clock->currTime + clock->timeStep) >= ringTimeEnd : - // (negative) - (clock->currTime > ringTimeEnd) && - (clock->currTime + clock->timeStep) <= ringTimeEnd; - } - - // if just turned on, reconstruct the rest of the state of this - // alarm event - if (ringing) { - // determine what ringBegin was for this alarm event TODO:sticky only? - //Alarm::resetRingBegin(positive); + // If the alarm is sticky and the ringer is turned off, then it cannot ring + // else calculate the ringing state of the alarm. + if(sticky) { + if (rc != ESMC_NULL_POINTER) *rc = ESMF_SUCCESS; + if(!ringerIsOn) return false; + } - // determine what the ending timeStepRingingCount was - // for this alarm event - timeStepRingingCount = - (int) ((clock->currTime - ringBegin) / clock->timeStep) + 1; - } + // Otherwise only the current state of the clock and alarm is used + // to determine if the alarm should ring. + Time clockTime = clock->currTime; + TimeInterval deltaT = clockTime - this->firstRingTime; - // otherwise check if time to turn *non-sticky* alarm back *off* in - // reverse mode (user is responsible for turning off *sticky* alarms via - // RingerOff()) - } else if (!sticky && ringing && enabled) { - if (timeStepRingingCount <= 1) { // if count down to last one - - // turn alarm off - ringingOnCurrTimeStep = ringing = false; - timeStepRingingCount = 0; - - // look back and reset ringing times for previous alarm event, - // if not past firstRingTime - // TODO: remove assumption of constant ringInterval; allow for - // variable ringIntervals - if (ringTime != firstRingTime) { - ringTime = prevRingTime; - prevRingTime -= ringInterval; - TimeInterval zeroTimeInterval(0,0,1,0,0,0); - if (ringTimeStepCount == 1 && - ringDuration != zeroTimeInterval) { // use ringDuration ... - ringTimeEnd = ringTime + ringDuration; - // ... otherwise use ringTimeStepCount - } else if (ringTimeStepCount >= 1) { - ringTimeEnd = ringTime + ringTimeStepCount * clock->timeStep; - } // TODO: else error, ringTimeStepCount <= 0 (ringing counter is - // always positive) Validate() ? - } else { // reset to initial condition - prevRingTime = ringTime; - } - - // determine what ringBegin was for *previous* alarm event - Alarm::resetRingBegin(positive); - - } else { // keep alarm ringing - // reverse count for how many clock time steps the alarm was ringing - timeStepRingingCount--; - } + ESMC_R8 rn = deltaT/ringInterval; - } // if (!sticky) + ESMC_I4 n = int(rn); - // reconstruct whether alarm was ringing on previous timeStep - if (enabled) { - ringingOnPrevTimeStep = (positive) ? - clock->prevTime >= ringTime && clock->prevTime < ringTimeEnd : - clock->prevTime <= ringTime && clock->prevTime > ringTimeEnd; - } +#ifdef DEBUG + printf("number of intervals %f %d \n", rn, n); +#endif - } // end if ESMF_DIRECTION_REVERSE + if( (this->firstRingTime + n *ringInterval == clockTime) || + (this->firstRingTime + (n+1)*ringInterval == clockTime) ) { + ringTime = clockTime; + ringing = true; + }else{ + ringing = false; + } if (rc != ESMC_NULL_POINTER) *rc = ESMF_SUCCESS; diff --git a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 index 128009563b..9e3da7f373 100644 --- a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 +++ b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 @@ -1043,7 +1043,7 @@ program ESMF_AlarmTest ! Test Setting the Alarm Time write(failMsg, *) " Returned ESMF_FAILURE" write(name, *) "Set Alarm Time Initialization Test" - call ESMF_TimeSet(alarmTime, yy=2003, mm=3, dd=13, h=5, & + call ESMF_TimeSet(alarmTime, yy=2003, mm=3, dd=13, h=5, m=45, s=27, & calkindflag=ESMF_CALKIND_GREGORIAN, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), & name, failMsg, result, ESMF_SRCLINE) From 8fefc23987db985684c15926bef2bf181f38c6e4 Mon Sep 17 00:00:00 2001 From: Fei Liu Date: Thu, 1 Jul 2021 11:38:32 -0400 Subject: [PATCH 02/32] Update alarm implementation and unit tests --- .../TimeMgr/include/ESMCI_Alarm.h | 2 + src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C | 72 +++--- .../TimeMgr/tests/ESMF_AlarmUTest.F90 | 234 ++++++++++++++++-- 3 files changed, 259 insertions(+), 49 deletions(-) diff --git a/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h b/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h index 93b5476cc6..185453835d 100644 --- a/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h +++ b/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h @@ -276,6 +276,8 @@ class Alarm { // enable Sticky void enableSticky(void); + bool willRingAtTime(const Time & clockTime) const; + // friend class alarm friend class Clock; diff --git a/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C b/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C index bdc4d020c7..1f382ece88 100644 --- a/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C +++ b/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C @@ -836,7 +836,9 @@ void Alarm::enableSticky(void){ // Initialize return code; assume routine not implemented if (rc != ESMC_NULL_POINTER) *rc = ESMF_SUCCESS; - return(enabled && ringing); + Time clockTime = clock->currTime; + + return(enabled && willRingAtTime(clockTime)); } // end Alarm::isRinging @@ -890,26 +892,10 @@ void Alarm::enableSticky(void){ } // get clock's next time + if (rc != ESMC_NULL_POINTER) *rc = ESMF_SUCCESS; Time clockNextTime; clock->Clock::getNextTime(&clockNextTime, timeStep); - - // if specified, use passed-in timestep, otherwise use clock's - TimeInterval tStep = (timeStep != ESMC_NULL_POINTER) ? - *timeStep : clock->timeStep; - - // get timestep direction: positive or negative - bool positive = tStep.TimeInterval::absValue() == tStep ? true : false; - - // check if alarm will turn on - bool willRing = false; - if (enabled) { - willRing = (positive) ? - clockNextTime >= ringTime && clock->currTime < ringTime : - clockNextTime <= ringTime && clock->currTime > ringTime; - } - - if (rc != ESMC_NULL_POINTER) *rc = ESMF_SUCCESS; - return(willRing); + return willRingAtTime(clockNextTime); } // end Alarm::willRingNext @@ -952,7 +938,10 @@ void Alarm::enableSticky(void){ if (rc != ESMC_NULL_POINTER) *rc = ESMF_SUCCESS; - return(ringingOnPrevTimeStep); + // get clock's prev time + if (rc != ESMC_NULL_POINTER) *rc = ESMF_SUCCESS; + Time clockTime = clock->currTime - clock->timeStep; + return willRingAtTime(clockTime); } // end Alarm::wasPrevRinging @@ -1090,6 +1079,29 @@ void Alarm::enableSticky(void){ } // end Alarm::isSticky +#define DEBUG 0 +bool Alarm::willRingAtTime(const Time & clockTime) const{ + bool retval = false; + + TimeInterval deltaT = clockTime - this->firstRingTime; + + ESMC_R8 rn = deltaT/ringInterval; + + ESMC_I4 n = int(rn); + +#ifdef DEBUG + printf("number of intervals %f %d \n", rn, n); +#endif + + if( (this->firstRingTime + n *ringInterval == clockTime) || + (this->firstRingTime + (n+1)*ringInterval == clockTime) ) + retval = true; + else + retval = false; + + return retval; +} + //------------------------------------------------------------------------- //BOP // !IROUTINE: Alarm::checkRingTime - check if time to ring @@ -1131,32 +1143,22 @@ void Alarm::enableSticky(void){ return(false); } -#define DEBUG 1 // If the alarm is sticky then whether it's ringing or not is controled // by ringerOn or ringerOff by user // If the alarm is sticky and the ringer is turned off, then it cannot ring // else calculate the ringing state of the alarm. if(sticky) { - if (rc != ESMC_NULL_POINTER) *rc = ESMF_SUCCESS; - if(!ringerIsOn) return false; + if(!ringerIsOn) { + if (rc != ESMC_NULL_POINTER) *rc = ESMF_SUCCESS; + return false; + } } // Otherwise only the current state of the clock and alarm is used // to determine if the alarm should ring. Time clockTime = clock->currTime; - TimeInterval deltaT = clockTime - this->firstRingTime; - - ESMC_R8 rn = deltaT/ringInterval; - - ESMC_I4 n = int(rn); - -#ifdef DEBUG - printf("number of intervals %f %d \n", rn, n); -#endif - - if( (this->firstRingTime + n *ringInterval == clockTime) || - (this->firstRingTime + (n+1)*ringInterval == clockTime) ) { + if (willRingAtTime( clockTime)){ ringTime = clockTime; ringing = true; }else{ diff --git a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 index 9e3da7f373..49364e9e11 100644 --- a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 +++ b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 @@ -1241,7 +1241,7 @@ program ESMF_AlarmTest write(failMsg, *) " Did not return ESMF_SUCCESS or returned wrong state" write(name, *) "Alarm Was Previously ringing Test" bool = ESMF_AlarmWasPrevRinging(alarm, rc=rc) - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(.not.bool), & + call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(bool), & name, failMsg, result, ESMF_SRCLINE) call ESMF_AlarmDestroy (alarm, rc=rc) call ESMF_ClockDestroy (clock, rc=rc) @@ -1308,7 +1308,7 @@ program ESMF_AlarmTest write(failMsg, *) " Did not return ESMF_SUCCESS or returned wrong state" write(name, *) "Alarm is still ringing Test" bool = ESMF_AlarmIsRinging(alarm, rc=rc) - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(.not.bool), & + call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(bool), & name, failMsg, result, ESMF_SRCLINE) ! ---------------------------------------------------------------------------- @@ -1331,7 +1331,7 @@ program ESMF_AlarmTest write(failMsg, *) " Did not return ESMF_SUCCESS or returned wrong state" write(name, *) "Alarm Was Previously ringing Test" bool = ESMF_AlarmWasPrevRinging(alarm, rc=rc) - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(.not.bool), & + call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(bool), & name, failMsg, result, ESMF_SRCLINE) @@ -3352,7 +3352,7 @@ program ESMF_AlarmTest call ESMF_ClockDestroy (clock, rc=rc) ! ---------------------------------------------------------------------------- -#if 0 +#if 1 ! The following tests are from Ben@NASA's support ticket 3614994 write(failMsg, *) " Alarms did not rewind correct number of times " write(name, *) "Test multiple alarms rewind correct number of times " @@ -3373,6 +3373,28 @@ program ESMF_AlarmTest if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. if (.not. testPass) print *, 'bad return codes discovered' call ESMF_Test (testPass, name, failMsg, result, ESMF_SRCLINE) + + ! ---------------------------------------------------------------------------- + + write(failMsg, *) " Alarms with ring intervals equal to clock interval, incorrect behavior " + write(name, *) "Test running an alarms forward-reverse-forward with ring interval equal to clock interval " + rc = ESMF_SUCCESS + testPass = .true. + call Test_AlarmAdvRewind(testPass, rc) + if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. + if (.not. testPass) print *, 'bad return codes discovered' + call ESMF_Test (testPass, name, failMsg, result, ESMF_SRCLINE) + + ! ---------------------------------------------------------------------------- + + write(failMsg, *) " Alarms reverse with sticky set... " + write(name, *) "Test running an alarm reverse with sticky bit set " + rc = ESMF_SUCCESS + testPass = .true. + call Test_RevAlarmSticky(60._ESMF_KIND_R8, testPass, rc) + if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. + if (.not. testPass) print *, 'bad return codes discovered' + call ESMF_Test (testPass, name, failMsg, result, ESMF_SRCLINE) #endif ! ---------------------------------------------------------------------------- @@ -3387,7 +3409,7 @@ program ESMF_AlarmTest ! finalize ESMF framework call ESMF_TestEnd(ESMF_SRCLINE) -#if 0 +#if 1 contains subroutine test_reverseAlarms(testPass, rc) @@ -3405,7 +3427,7 @@ subroutine test_reverseAlarms(testPass, rc) type(ESMF_TimeInterval) :: tint type(ESMF_Alarm) :: esmfalarm, firstalarm - integer :: i,nstep + integer :: i,nstep, nrings1, nrings2 type(ESMF_Time) :: time character(len=10) :: iam='test_clock' @@ -3442,13 +3464,16 @@ subroutine test_reverseAlarms(testPass, rc) call ESMF_TimeIntervalSet(tint,h=1,rc=status) call verify_(status) esmfalarm = ESMF_AlarmCreate(clock=clock,ringInterval=tint,ringTime=start_time,sticky=.false.,name="alarm2",rc=status) + nrings1 = 0 + nrings2 = 0 do i=1,nstep call ESMF_ClockGet(clock,currTime=time) esmf_ring = ESMF_AlarmIsRinging(esmfalarm,rc=status) call verify_(status) if ( esmf_ring) then - !write(*,*)'ringing' - !call ESMF_TimePrint(time,options='string') + write(*,*)'ringing' + call ESMF_TimePrint(time,options='string') + nrings2=nrings2 + 1 end if call ESMF_ClockAdvance(clock) enddo @@ -3458,28 +3483,28 @@ subroutine test_reverseAlarms(testPass, rc) i = 0 do i = i + 1 - !write(*,*) 'Rewind step: ', i + write(*,*) 'Rewind step: ', i call ESMF_ClockAdvance(clock,rc=status) call verify_(status) call ESMF_ClockGet(clock,currTime=time) if (ESMF_AlarmIsRinging(esmfalarm)) then - !write(*,*)'rewinding one step ',ESMF_AlarmIsRinging(esmfalarm) + write(*,*)'rewinding one step ',ESMF_AlarmIsRinging(esmfalarm) n_rings = n_rings + 1 - !call ESMF_TimePrint(time,options='string') + call ESMF_TimePrint(time,options='string') end if if (time == start_time) exit enddo call ESMF_ClockSet(clock, direction=ESMF_DIRECTION_FORWARD, rc=status) call verify_(status) - !write(*,*)"*************** end rewind *********************" + write(*,*)"*************** end rewind *********************" do i=1,nstep*2 call ESMF_ClockGet(clock,currTime=time) esmf_ring = ESMF_AlarmIsRinging(esmfalarm,rc=status) call verify_(status) if ( esmf_ring ) then - !write(*,*)'ringing' - !call ESMF_TimePrint(time,options='string') + write(*,*)'ringing' + call ESMF_TimePrint(time,options='string') end if call ESMF_ClockAdvance(clock) enddo @@ -3601,6 +3626,187 @@ subroutine Test_AlarmHang(testPass, rc) testPass = .true. end subroutine Test_AlarmHang + +subroutine Test_AlarmAdvRewind(testPass, rc) + logical, intent(out) :: testPass + integer :: rc + + type(ESMF_TimeInterval) :: dt + type(ESMF_Time) :: start_time, clock_start, clock_end + type(ESMF_Clock) :: clock + + type(ESMF_TimeInterval) :: tint + + integer :: status,i,j,nstep, nrings(2) + + logical :: esmf_ring + character(len=ESMF_MAXSTR) :: alarm_name + integer :: nalarms + type(ESMF_Alarm), allocatable :: alarm_list(:) + type(ESMF_Time) :: time + type(ESMF_Alarm) :: esmfalarm + type(ESMF_CalKind_Flag) :: calkindflag + + rc = ESMF_SUCCESS + + !call ESMF_CalendarGet(calkindflag=calkindflag, rc=status) + !call verify_(status) + call ESMF_CalendarSetDefault ( ESMF_CALKIND_GREGORIAN, rc=status ) + call verify_(status) + call ESMF_TimeSet(clock_start,yy=2000,mm=1,dd=1,h=21,m=0,s=0,rc=status) + call verify_(status) + call ESMF_TimeSet(clock_end,yy=2000,mm=12,dd=1,h=21,m=0,s=0,rc=status) + call verify_(status) + call ESMF_TimeSet(start_time,yy=2000,mm=10,dd=1,h=21,m=0,s=0,rc=status) + call verify_(status) + call ESMF_TimeIntervalSet(dt,S=900, sN=0, sD=1,rc=status) + call verify_(status) + clock= ESMF_ClockCreate(timeStep=dt,startTime=clock_start,stopTime=clock_end,rc=status) + call verify_(status) + call ESMF_ClockSet(clock,currTime=start_time,rc=status) + call verify_(status) + + ! fails if s=900 + call ESMF_TimeIntervalSet(tint,s=900) + esmfalarm = ESMF_AlarmCreate(clock=clock,ringInterval=tint,ringTime=start_time,sticky=.false.,name='alarm_900',rc=status) + call verify_(status) + ! works if s=1800 + call ESMF_TimeIntervalSet(tint,s=1800) + esmfalarm = ESMF_AlarmCreate(clock=clock,ringInterval=tint,ringTime=start_time,sticky=.false.,name='alarm_1800',rc=status) + call verify_(status) + + + nstep=12 + nrings=0 + call ESMF_ClockGet(clock,currtime=start_time,alarmCount=nalarms,rc=status) + allocate(alarm_list(nalarms)) + call ESMF_ClockGetAlarmList(clock, alarmListFlag=ESMF_ALARMLIST_ALL, alarmList=alarm_list) + + do i=1,nstep + call ESMF_ClockGet(clock,currTime=time) + do j = 1,nalarms + call ESMF_AlarmGet(alarm_list(j),name=alarm_name) + esmf_ring = ESMF_AlarmIsRinging(alarm_list(j),rc=status) + call verify_(status) + if ( esmf_ring) then + nrings(j) = nrings(j) + 1 + write(*,*)trim(alarm_name)//' is ringing' + call ESMF_TimePrint(time,options='string') + end if + end do + call ESMF_ClockAdvance(clock) + enddo + call ESMF_ClockSet(clock, direction=ESMF_DIRECTION_REVERSE, rc=status) + call verify_(status) + write(*,*)"*************** start rewind *********************" + nrings=0 + do + call ESMF_ClockAdvance(clock,rc=status) + call verify_(status) + call ESMF_ClockGet(clock,currTime=time) + do j=1,nalarms + call ESMF_AlarmGet(alarm_list(j),name=alarm_name) + if (ESMF_AlarmIsRinging(alarm_list(j))) then + nrings(j) = nrings(j) + 1 + write(*,*)trim(alarm_name)//' is ringing' + call ESMF_TimePrint(time,options='string') + end if + end do + + if (time == start_time) exit + enddo + call ESMF_ClockSet(clock, direction=ESMF_DIRECTION_FORWARD, rc=status) + call verify_(status) + write(*,*)"*************** end rewind *********************" + nrings=0 + do i=1,nstep*2 + call ESMF_ClockGet(clock,currTime=time) + do j = 1,nalarms + call ESMF_AlarmGet(alarm_list(j),name=alarm_name) + esmf_ring = ESMF_AlarmIsRinging(alarm_list(j),rc=status) + call verify_(status) + if ( esmf_ring) then + nrings(j) = nrings(j) + 1 + write(*,*)trim(alarm_name)//' is ringing' + call ESMF_TimePrint(time,options='string') + end if + end do + call ESMF_ClockAdvance(clock) + enddo + +end subroutine Test_AlarmAdvRewind + +subroutine Test_RevAlarmSticky(dt, testPass, rc) +#define CONTEXT line=__LINE__,file=__FILE__ +#define CHECKRC if(ESMF_LogFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,CONTEXT,rcToReturn=rc))then;write(0,*)'app abort: ',__FILE__,__LINE__;return;endif + logical, intent(out) :: testPass + integer, parameter :: r8 = SELECTED_REAL_KIND(12) ! real r8 + real(kind=r8), intent(in) :: dt + integer :: rc + + type(ESMF_Clock) :: clock + type(ESMF_Alarm) :: alarm + type(ESMF_TimeInterval) :: esmf_ival + type(ESMF_Time) :: time, initial, finish, ring_time + real(kind=r8) :: secs + logical :: reverse_clock, sticky_alarm + + rc = ESMF_SUCCESS + + call ESMF_Initialize( defaultcalkind=ESMF_CALKIND_GREGORIAN, rc=rc ) ; CHECKRC + call ESMF_TimeSet(time, yy=2021, mm=4, dd=6, rc=rc) ; CHECKRC + + secs = 0 + call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) ; CHECKRC + initial = time + esmf_ival + + secs = dt*100 + call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) ; CHECKRC + finish = time + esmf_ival + + secs = dt + call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) ; CHECKRC + + clock = ESMF_Clockcreate(timeStep=esmf_ival & + ,startTime=initial,stopTime=finish & + ,refTime=time, rc=rc ) ; CHECKRC + + call ESMF_ClockSet(clock,direction=ESMF_DIRECTION_REVERSE, rc=rc) ; CHECKRC + + reverse_clock = ESMF_ClockIsReverse(clock, rc=rc) ; CHECKRC + sticky_alarm = .not.reverse_clock + + write(0,'("reverse =",x,l)') reverse_clock + write(0,'("sticky =",x,l)') sticky_alarm + + secs = dt*50 + call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) ; CHECKRC + ring_time = initial + esmf_ival + +#if 1 + alarm = ESMF_AlarmCreate(clock, ringTime=ring_time, sticky=sticky_alarm, & + ringTimeStepCount=1, rc=rc) ; CHECKRC +#else + alarm = ESMF_AlarmCreate(clock, ringTime=ring_time, sticky=.false., & + ringTimeStepCount=1, rc=rc) ; CHECKRC +#endif + + call ESMF_alarmPrint(alarm,options='sticky') + + testPass = .true. ! Because the C++ runtime failure cannot be caught reliably, set this to false. + +#undef CONTEXT +#undef CHECKRC +end subroutine Test_RevAlarmSticky + + subroutine verify_(rc) + integer, intent(in) :: rc + + integer :: error_code,status + if (rc /=0) then + call ESMF_Finalize() + end if + end subroutine verify_ #endif end program ESMF_AlarmTest From a6f1a2b43a71a6244e4e8d3d8ef0d85f90aab4d1 Mon Sep 17 00:00:00 2001 From: Fei Liu Date: Mon, 19 Jul 2021 11:20:37 -0400 Subject: [PATCH 03/32] Fix ringTime reset when alarm is created --- src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C | 3 +- .../TimeMgr/tests/ESMF_AlarmUTest.F90 | 84 ++++++++++++++++++- 2 files changed, 84 insertions(+), 3 deletions(-) diff --git a/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C b/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C index 1f382ece88..76422a2e6c 100644 --- a/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C +++ b/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C @@ -1089,7 +1089,7 @@ bool Alarm::willRingAtTime(const Time & clockTime) const{ ESMC_I4 n = int(rn); -#ifdef DEBUG +#if DEBUG == 1 printf("number of intervals %f %d \n", rn, n); #endif @@ -1159,7 +1159,6 @@ bool Alarm::willRingAtTime(const Time & clockTime) const{ // to determine if the alarm should ring. Time clockTime = clock->currTime; if (willRingAtTime( clockTime)){ - ringTime = clockTime; ringing = true; }else{ ringing = false; diff --git a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 index 49364e9e11..a132713449 100644 --- a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 +++ b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 @@ -3395,6 +3395,17 @@ program ESMF_AlarmTest if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. if (.not. testPass) print *, 'bad return codes discovered' call ESMF_Test (testPass, name, failMsg, result, ESMF_SRCLINE) + + ! ---------------------------------------------------------------------------- + + write(failMsg, *) " Alarms with ClockSet... " + write(name, *) "Test ClockSet after alarm attached to clock " + rc = ESMF_SUCCESS + testPass = .true. + call Test_ClockSet(testPass, rc) + if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. + if (.not. testPass) print *, 'bad return codes discovered' + call ESMF_Test (testPass, name, failMsg, result, ESMF_SRCLINE) #endif ! ---------------------------------------------------------------------------- @@ -3753,7 +3764,6 @@ subroutine Test_RevAlarmSticky(dt, testPass, rc) rc = ESMF_SUCCESS - call ESMF_Initialize( defaultcalkind=ESMF_CALKIND_GREGORIAN, rc=rc ) ; CHECKRC call ESMF_TimeSet(time, yy=2021, mm=4, dd=6, rc=rc) ; CHECKRC secs = 0 @@ -3807,6 +3817,78 @@ subroutine verify_(rc) call ESMF_Finalize() end if end subroutine verify_ + +subroutine Test_ClockSet(testPass, rc) +#define CONTEXT line=__LINE__,file=__FILE__ +#define CHECKRC if(ESMF_LogFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,CONTEXT,rcToReturn=rc))then;write(0,*)'app abort: ',__FILE__,__LINE__;return;endif + logical, intent(out) :: testPass + integer, parameter :: r8 = SELECTED_REAL_KIND(12) ! real r8 + integer :: rc + + type(ESMF_Clock) :: clock + type(ESMF_Alarm) :: alarm + type(ESMF_TimeInterval) :: esmf_ival + type(ESMF_Time) :: time, initial, finish, ring_time + real(kind=r8) :: secs + logical :: reverse_clock, sticky_alarm + + rc = ESMF_SUCCESS + + call ESMF_TimeSet(time, yy=2021, mm=4, dd=6, rc=rc) ; CHECKRC + + secs = 0 + call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) ; CHECKRC + initial = time + esmf_ival + call ESMF_TimePrint(initial, options="string", rc=rc) ; CHECKRC + + secs = 6000 + call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) ; CHECKRC + finish = time + esmf_ival + call ESMF_TimePrint(finish, options="string", rc=rc) ; CHECKRC + + secs = 60 + call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) ; CHECKRC + + clock = ESMF_Clockcreate(timeStep=esmf_ival & + ,startTime=initial,stopTime=finish & + ,refTime=time, rc=rc ) ; CHECKRC + + call ESMF_ClockSet(clock,direction=ESMF_DIRECTION_REVERSE, rc=rc) ; CHECKRC + + reverse_clock = ESMF_ClockIsReverse(clock, rc=rc) ; CHECKRC + sticky_alarm = .not.reverse_clock + + write(0,'("reverse =",x,l)') reverse_clock + write(0,'("sticky =",x,l)') sticky_alarm + + secs = 3000 + call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) ; CHECKRC + ring_time = initial + esmf_ival + print *, 'Before Alarm Create ringTime: ' + call ESMF_TimePrint(ring_time, options="string", rc=rc) ; CHECKRC +#if 1 + alarm = ESMF_AlarmCreate(clock, ringTime=ring_time, sticky=sticky_alarm, & + ringTimeStepCount=1, rc=rc) ; CHECKRC +#else + alarm = ESMF_AlarmCreate(clock, ringTime=ring_time, sticky=.false., & + ringTimeStepCount=1, rc=rc) ; CHECKRC +#endif + + call ESMF_TimePrint(ring_time, options="string", rc=rc) ; CHECKRC + call ESMF_AlarmGet(alarm, ringTime=ring_time, rc=rc) ; CHECKRC + print *, 'After Alarm Create ringTime: ' + call ESMF_TimePrint(ring_time, options="string", rc=rc) ; CHECKRC + + call ESMF_ClockSet(clock, stopTime=ring_time, rc=rc) ; CHECKRC + + call ESMF_alarmPrint(alarm,options='sticky') + + testPass = .true. ! Because the C++ runtime failure cannot be caught reliably, set this to false. + +#undef CONTEXT +#undef CHECKRC +end subroutine Test_ClockSet + #endif end program ESMF_AlarmTest From 289bc0834ac12f06c1f1ea678b52f1e5b61d0913 Mon Sep 17 00:00:00 2001 From: Fei Liu Date: Wed, 28 Jul 2021 12:24:23 -0400 Subject: [PATCH 04/32] Notify user with error message to clarify the cause of writeVTK falilure --- src/Infrastructure/XGrid/src/ESMF_XGrid.F90 | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Infrastructure/XGrid/src/ESMF_XGrid.F90 b/src/Infrastructure/XGrid/src/ESMF_XGrid.F90 index d9be4409c2..18764a2636 100644 --- a/src/Infrastructure/XGrid/src/ESMF_XGrid.F90 +++ b/src/Infrastructure/XGrid/src/ESMF_XGrid.F90 @@ -1313,6 +1313,11 @@ subroutine ESMF_XGridWriteVTK(xgrid, filename, & if (ESMF_LogFoundError(localrc, & ESMF_ERR_PASSTHRU, & ESMF_CONTEXT, rcToReturn=rc)) return + else + call ESMF_LogSetError(rcToCheck=ESMF_RC_OBJ_BAD, & + msg="The XGrid mesh was not stored during XGrid creation, re-create XGrid with storeOverlay set to .true.", & + ESMF_CONTEXT, rcToReturn=rc) + return endif if (present(rc)) rc = ESMF_SUCCESS From 3e96719bd118536f72cb869d5103078094905dd2 Mon Sep 17 00:00:00 2001 From: Fei Liu Date: Thu, 5 Aug 2021 11:42:18 -0400 Subject: [PATCH 05/32] Update ringTime and prevRingTime --- .../TimeMgr/include/ESMCI_Alarm.h | 1 + src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C | 29 +++++ src/Infrastructure/TimeMgr/src/ESMCI_Clock.C | 1 + .../TimeMgr/tests/ESMF_AlarmUTest.F90 | 103 ++++++++++++++++++ 4 files changed, 134 insertions(+) diff --git a/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h b/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h index 185453835d..71f0da1ead 100644 --- a/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h +++ b/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h @@ -219,6 +219,7 @@ class Alarm { // Check for crossing ringTime in either positive or // negative direction // Can be basis for asynchronous alarm reporting + void updateRingTime(int *rc=0); bool operator==(const Alarm &) const; bool operator!=(const Alarm &) const; diff --git a/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C b/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C index 76422a2e6c..e1e48fb260 100644 --- a/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C +++ b/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C @@ -1170,6 +1170,35 @@ bool Alarm::willRingAtTime(const Time & clockTime) const{ } // end Alarm::checkRingTime +//------------------------------------------------------------------------- +//BOP +// !IROUTINE: Alarm::updateRingTime - update Alarm Ring Time +// +// !INTERFACE: + void Alarm::updateRingTime( +// +// !RETURN VALUE: +// bool is ringing or not +// +// !ARGUMENTS: + int *rc) { // out - error return code + +// !DESCRIPTION: +// Update ringTime and prevRingTime +// +//EOP +// !REQUIREMENTS: TMG4.4, 4.6 + + #undef ESMC_METHOD + #define ESMC_METHOD "ESMCI::Alarm::updateRingTime()" + + if(ringing){ + prevRingTime = ringTime; + ringTime = clock->currTime; + } + +} + //------------------------------------------------------------------------- //BOP // !IROUTINE: Alarm(==) - Alarm equality comparison diff --git a/src/Infrastructure/TimeMgr/src/ESMCI_Clock.C b/src/Infrastructure/TimeMgr/src/ESMCI_Clock.C index 720e37c001..d7b3236555 100644 --- a/src/Infrastructure/TimeMgr/src/ESMCI_Clock.C +++ b/src/Infrastructure/TimeMgr/src/ESMCI_Clock.C @@ -645,6 +645,7 @@ int Clock::count=0; // check each alarm to see if it's time to ring ringing = alarmList[i]->Alarm::checkRingTime(&rc); + if(ringing) alarmList[i]->Alarm::updateRingTime(&rc); // report ringing alarms if requested if (ringing) { diff --git a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 index a132713449..76a343c7c4 100644 --- a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 +++ b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 @@ -3406,6 +3406,16 @@ program ESMF_AlarmTest if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. if (.not. testPass) print *, 'bad return codes discovered' call ESMF_Test (testPass, name, failMsg, result, ESMF_SRCLINE) + ! ---------------------------------------------------------------------------- + + write(failMsg, *) " Alarms with getPrevRingTime... " + write(name, *) "Test getPrevRingTime... after alarm attached to clock " + rc = ESMF_SUCCESS + testPass = .true. + call Test_GetPrevRingTime(testPass, rc) + if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. + if (.not. testPass) print *, 'bad return codes discovered' + call ESMF_Test (testPass, name, failMsg, result, ESMF_SRCLINE) #endif ! ---------------------------------------------------------------------------- @@ -3889,6 +3899,99 @@ subroutine Test_ClockSet(testPass, rc) #undef CHECKRC end subroutine Test_ClockSet +subroutine Test_GetPrevRingTime(testPass, rc) +#define CONTEXT line=__LINE__,file=__FILE__ +#define CHECKRC if(ESMF_LogFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,CONTEXT,rcToReturn=rc))then;write(0,*)'app abort: ',__FILE__,__LINE__;return;endif + logical, intent(out) :: testPass + integer, parameter :: r8 = SELECTED_REAL_KIND(12) ! real r8 + integer :: rc + + type(ESMF_Clock) :: clock + type(ESMF_Alarm) :: alarm + type(ESMF_TimeInterval) :: esmf_ival, diffTime + type(ESMF_Time) :: time, initial, finish, ring_time, ringTime, prevTime + real(kind=r8) :: secs + logical :: reverse_clock, sticky_alarm, esmf_ring + integer :: i, nstep = 6, nrings + + rc = ESMF_SUCCESS + testPass = .true. + + call ESMF_TimeSet(time, yy=2021, mm=4, dd=6, rc=rc) ; CHECKRC + + secs = 0 + call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) ; CHECKRC + initial = time + esmf_ival + call ESMF_TimePrint(initial, options="string", rc=rc) ; CHECKRC + + secs = 6000 + call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) ; CHECKRC + finish = time + esmf_ival + call ESMF_TimePrint(finish, options="string", rc=rc) ; CHECKRC + + secs = 60 + call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) ; CHECKRC + + clock = ESMF_Clockcreate(timeStep=esmf_ival & + ,startTime=initial,stopTime=finish & + ,refTime=time, rc=rc ) ; CHECKRC + + secs = 120 ! alarm step is clock step x 2 + call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) ; CHECKRC + ring_time = initial + alarm = ESMF_AlarmCreate(clock, ringTime=ring_time, ringInterval=esmf_ival, & + rc=rc) ; CHECKRC + nrings = 0 + do i=1,nstep + call ESMF_ClockAdvance(clock) + call ESMF_ClockGet(clock,currTime=time) + esmf_ring = ESMF_AlarmIsRinging(alarm, rc=rc) + call verify_(rc) + if ( esmf_ring) then + nrings = nrings + 1 + write(*,*) 'alarm is ringing' + call ESMF_TimePrint(time,options='string') + call ESMF_AlarmGet(alarm, ringTime=ringTime, prevRingTime=prevTime, rc=rc) + call verify_(rc) + write(*,*) 'prev Ring Time' + call ESMF_TimePrint(prevTime,options='string') + write(*,*) 'Ring Time' + call ESMF_TimePrint(ringTime,options='string') + + diffTime = ringTime - prevTime + if(diffTime /= esmf_ival) testPass = .false. ! both should be 20 minutes or 120 seconds + end if + enddo + +! call ESMF_ClockSet(clock,direction=ESMF_DIRECTION_REVERSE, rc=rc) ; CHECKRC +! +! reverse_clock = ESMF_ClockIsReverse(clock, rc=rc) ; CHECKRC +! sticky_alarm = .not.reverse_clock +! +! write(0,'("reverse =",x,l)') reverse_clock +! write(0,'("sticky =",x,l)') sticky_alarm +! +! secs = 3000 +! call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) ; CHECKRC +! ring_time = initial + esmf_ival +! print *, 'Before Alarm Create ringTime: ' +! call ESMF_TimePrint(ring_time, options="string", rc=rc) ; CHECKRC +! +! call ESMF_TimePrint(ring_time, options="string", rc=rc) ; CHECKRC +! call ESMF_AlarmGet(alarm, ringTime=ring_time, rc=rc) ; CHECKRC +! print *, 'After Alarm Create ringTime: ' +! call ESMF_TimePrint(ring_time, options="string", rc=rc) ; CHECKRC +! +! call ESMF_ClockSet(clock, stopTime=ring_time, rc=rc) ; CHECKRC +! +! call ESMF_alarmPrint(alarm,options='sticky') + + +#undef CONTEXT +#undef CHECKRC +end subroutine Test_GetPrevRingTime + + #endif end program ESMF_AlarmTest From 44cc0178fa161e38ee873b62540eddf408c5b225 Mon Sep 17 00:00:00 2001 From: Fei Liu Date: Mon, 16 Aug 2021 11:05:53 -0400 Subject: [PATCH 06/32] Add ringerIsOn as a part of isRinging check --- src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C b/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C index e1e48fb260..bc9618d2a5 100644 --- a/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C +++ b/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C @@ -838,7 +838,7 @@ void Alarm::enableSticky(void){ Time clockTime = clock->currTime; - return(enabled && willRingAtTime(clockTime)); + return(enabled && ringerIsOn && willRingAtTime(clockTime)); } // end Alarm::isRinging @@ -1142,6 +1142,12 @@ bool Alarm::willRingAtTime(const Time & clockTime) const{ ESMC_LogDefault.Write(logMsg, ESMC_LOGMSG_WARN,ESMC_CONTEXT); return(false); } + if(!ringerIsOn) { + if (rc != ESMC_NULL_POINTER) *rc = ESMF_SUCCESS; + return false; + } + + // If the ringing is controlled by ringer, the following logic is redundant. // If the alarm is sticky then whether it's ringing or not is controled // by ringerOn or ringerOff by user From 8659caee8219593466691f9cb6dbe9d89248be78 Mon Sep 17 00:00:00 2001 From: Fei Liu Date: Mon, 13 Sep 2021 11:37:06 -0400 Subject: [PATCH 07/32] update alarm ringing calculation --- .../TimeMgr/include/ESMCI_Alarm.h | 5 +- .../TimeMgr/interface/ESMCI_Alarm_F.C | 5 +- .../TimeMgr/interface/ESMF_Alarm.F90 | 8 +- .../TimeMgr/interface/ESMF_Clock.F90 | 151 +++++++++++++++++- src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C | 71 ++++---- src/Infrastructure/TimeMgr/src/ESMCI_Clock.C | 1 - 6 files changed, 192 insertions(+), 49 deletions(-) diff --git a/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h b/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h index 71f0da1ead..6c27ea821f 100644 --- a/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h +++ b/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h @@ -195,7 +195,8 @@ class Alarm { bool *ringing=0, bool *ringingOnPrevTimeStep=0, bool *enabled=0, // (TMG 4.1, 4.7) - bool *sticky=0); + bool *sticky=0, + bool *ringerIsOn=0); int enable(void); // TMG4.5.3 int disable(void); @@ -277,7 +278,7 @@ class Alarm { // enable Sticky void enableSticky(void); - bool willRingAtTime(const Time & clockTime) const; + bool canRingAtTime(const Time & clockTime) const; // friend class alarm friend class Clock; diff --git a/src/Infrastructure/TimeMgr/interface/ESMCI_Alarm_F.C b/src/Infrastructure/TimeMgr/interface/ESMCI_Alarm_F.C index 1b3bcce4de..627f808a7f 100644 --- a/src/Infrastructure/TimeMgr/interface/ESMCI_Alarm_F.C +++ b/src/Infrastructure/TimeMgr/interface/ESMCI_Alarm_F.C @@ -108,7 +108,7 @@ extern "C" { TimeInterval *ringDuration, int *ringTimeStepCount, int *timeStepRingingCount, Time *ringBegin, Time *ringEnd, Time *refTime, bool *ringing, - bool *ringingOnPrevTimeStep, bool *enabled, bool *sticky, + bool *ringingOnPrevTimeStep, bool *enabled, bool *sticky, bool *ringerIsOn, int *status, ESMCI_FortranStrLenArg tempName_l) { ESMF_CHECK_POINTER(*ptr, status) @@ -131,7 +131,8 @@ extern "C" { ESMC_NOT_PRESENT_FILTER(ringing), ESMC_NOT_PRESENT_FILTER(ringingOnPrevTimeStep), ESMC_NOT_PRESENT_FILTER(enabled), - ESMC_NOT_PRESENT_FILTER(sticky) ); + ESMC_NOT_PRESENT_FILTER(sticky), + ESMC_NOT_PRESENT_FILTER(ringerIsOn) ); if (ESMC_PRESENT(status)) *status = rc; } diff --git a/src/Infrastructure/TimeMgr/interface/ESMF_Alarm.F90 b/src/Infrastructure/TimeMgr/interface/ESMF_Alarm.F90 index b55637cc1d..1ee7b10823 100644 --- a/src/Infrastructure/TimeMgr/interface/ESMF_Alarm.F90 +++ b/src/Infrastructure/TimeMgr/interface/ESMF_Alarm.F90 @@ -662,7 +662,7 @@ end subroutine ESMF_AlarmEnable subroutine ESMF_AlarmGet(alarm, keywordEnforcer, & clock, ringTime, prevRingTime, ringInterval, stopTime, ringDuration, & ringTimeStepCount, timeStepRingingCount, ringBegin, ringEnd, & - refTime, ringing, ringingOnPrevTimeStep, enabled, sticky, name, rc) + refTime, ringing, ringingOnPrevTimeStep, enabled, sticky, ringerIsOn, name, rc) ! !ARGUMENTS: type(ESMF_Alarm), intent(in) :: alarm @@ -682,6 +682,7 @@ subroutine ESMF_AlarmGet(alarm, keywordEnforcer, & logical, intent(out), optional :: ringingOnPrevTimeStep logical, intent(out), optional :: enabled logical, intent(out), optional :: sticky + logical, intent(out), optional :: ringerIsOn character (len=*), intent(out), optional :: name integer, intent(out), optional :: rc @@ -746,6 +747,9 @@ subroutine ESMF_AlarmGet(alarm, keywordEnforcer, & ! \item[{[sticky]}] ! The sticky state. ! See also {\tt ESMF\_AlarmSticky()}, {\tt ESMF\_AlarmNotSticky()}. +! \item[{[ringerIsOn]}] +! The ringer state. +! See also {\tt ESMF\_AlarmRingerOn()}, {\tt ESMF\_AlarmRingerOff()}. ! \item[{[name]}] ! The name of this alarm. ! \item[{[rc]}] @@ -782,7 +786,7 @@ subroutine ESMF_AlarmGet(alarm, keywordEnforcer, & ringTime, prevRingTime, ringInterval, stopTime, & ringDuration, ringTimeStepCount, & timeStepRingingCount, ringBegin, ringEnd, refTime, & - ringing, ringingOnPrevTimeStep, enabled, sticky, localrc) + ringing, ringingOnPrevTimeStep, enabled, sticky, ringerIsOn, localrc) if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & ESMF_CONTEXT, rcToReturn=rc)) return diff --git a/src/Infrastructure/TimeMgr/interface/ESMF_Clock.F90 b/src/Infrastructure/TimeMgr/interface/ESMF_Clock.F90 index 2c7a9bbb23..ff57c98bd5 100644 --- a/src/Infrastructure/TimeMgr/interface/ESMF_Clock.F90 +++ b/src/Infrastructure/TimeMgr/interface/ESMF_Clock.F90 @@ -51,7 +51,8 @@ module ESMF_ClockMod use ESMF_TimeMod use ESMF_TimeTypeMod use ESMF_AlarmTypeMod - + use ESMF_AlarmMod + use ESMF_VMMod ! type definition for this module use ESMF_ClockTypeMod @@ -113,6 +114,11 @@ module ESMF_ClockMod private ESMF_ClockCreateNew private ESMF_ClockCreateCopy +! !PUBLIC MEMBER FUNCTIONS: + public ESMF_TimeDebug + public ESMF_TimeIntervalDebug + public ESMF_AlarmDebug + public ESMF_ClockDebug !------------------------------------------------------------------------------ ! The following line turns the CVS identifier string into a printable variable. character(*), parameter, private :: version = & @@ -2062,5 +2068,148 @@ function ESMF_ClockNE(clock1, clock2) end function ESMF_ClockNE !------------------------------------------------------------------------------ +#undef ESMF_METHOD +#define ESMF_METHOD "ESMF_TimeIntervalDebug()" + + subroutine ESMF_TimeIntervalDebug(TimeIV, name, rc) + type (ESMF_TimeInterval), intent(in) :: TimeIV + character(len=*), intent(in) :: name + integer, intent(out) :: rc + + type (ESMF_VM) :: vm + integer :: lpet, npet, yy, mm, dd, d, h, m, s + + rc = ESMF_SUCCESS + call ESMF_VMGetCurrent(vm, rc=rc) + if (ESMF_LogFoundError(rc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + + call ESMF_VMGet(vm, localpet =lpet, petcount=npet, rc=rc) + if (ESMF_LogFoundError(rc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + + call ESMF_TimeIntervalGet(TimeIV, yy=yy, mm=mm, d=d, h=h, m=m, s=s, rc=rc) + if (ESMF_LogFoundError(rc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + + if(lpet == 0) then + write(*, '(A, A, 2I4, I10, 3I4)') 'TimeInterval Debug Printout: ', name, yy, mm, d, h, m, s + endif + + end subroutine ESMF_TimeIntervalDebug + +#undef ESMF_METHOD +#define ESMF_METHOD "ESMF_TimeDebug()" + subroutine ESMF_TimeDebug(Time, name, rc) + type (ESMF_Time), intent(in) :: Time + character(len=*), intent(in) :: name + integer, intent(out) :: rc + + type (ESMF_VM) :: vm + integer :: lpet, npet, yy, mm, dd, d, h, m, s + + rc = ESMF_SUCCESS + call ESMF_VMGetCurrent(vm, rc=rc) + if (ESMF_LogFoundError(rc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + + call ESMF_VMGet(vm, localpet =lpet, petcount=npet, rc=rc) + if (ESMF_LogFoundError(rc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + + call ESMF_TimeGet(Time, yy=yy, mm=mm, dd=dd, d=d, h=h, m=m, s=s, rc=rc) + if (ESMF_LogFoundError(rc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + + if(lpet == 0) then + write(*, '(A, A, 3I4, I10, 3I4)') 'Time Debug Printout: ', name, yy, mm, dd, d, h, m, s + endif + + end subroutine ESMF_TimeDebug + +#undef ESMF_METHOD +#define ESMF_METHOD "ESMF_AlarmDebug()" + subroutine ESMF_AlarmDebug(alarm, name, rc) + type (ESMF_Alarm), intent(in) :: alarm + character(len=*), intent(in) :: name + integer, intent(out) :: rc + + type (ESMF_VM) :: vm + integer :: lpet, npet + logical :: ringing, enabled, sticky, ringingOnPrevTimeStep, ringerIsOn + type (ESMF_Time) :: ringTime, refTime, prevRingTime, stopTime, ringBegin, ringEnd, ringRef + type (ESMF_TimeInterval) :: ringInterval, ringDuration + + rc = ESMF_SUCCESS + + call ESMF_VMGetCurrent(vm, rc=rc) + if (ESMF_LogFoundError(rc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + + call ESMF_VMGet(vm, localpet =lpet, petcount=npet, rc=rc) + if (ESMF_LogFoundError(rc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + + ringing = .false. + enabled = .false. + sticky = .false. + ringerIsOn = .false. + + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, ringerIsOn=ringerIsOn, & + ringTime=ringTime, refTime=refTime, stopTime=stopTime, ringBegin=ringBegin, ringEnd=ringEnd, & + ringInterval=ringInterval, ringDuration=ringDuration, rc=rc) + if (ESMF_LogFoundError(rc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + + if(lpet == 0) then + write(*, '(A,A)') 'Alarm Debug Printout: ', name + print *, '' + print *, 'ringing = ', ringing + print *, 'enabled = ', enabled + print *, 'sticky = ' , sticky + print *, 'ringerIsOn = ' , ringerIsOn + call ESMF_TimeDebug(ringTime, 'ringTime', rc=rc) + call ESMF_TimeDebug(refTime, 'refTime', rc=rc) + !call ESMF_TimeDebug(stopTime, 'stopTime', rc=rc) + !call ESMF_TimeDebug(ringBegin, 'ringBegin', rc=rc) + !call ESMF_TimeDebug(ringEnd, 'ringEnd', rc=rc) + call ESMF_TimeIntervalDebug(ringInterval, 'ringInterval', rc=rc) + call ESMF_TimeIntervalDebug(ringDuration, 'ringDuration', rc=rc) + + endif + end subroutine ESMF_AlarmDebug + + subroutine ESMF_ClockDebug(clock, name, rc) + type (ESMF_Clock), intent(in) :: clock + character(len=*), intent(in) :: name + integer, intent(out) :: rc + + type (ESMF_VM) :: vm + integer :: lpet, npet, alarmCount + logical :: ringing, enabled, sticky, ringingOnPrevTimeStep, alarmRinging + type (ESMF_Time) :: currTime, ringTime, prevRingTime, stopTime, ringBegin, ringEnd, ringRef + type (ESMF_TimeInterval) :: ringInterval, ringDuration + + rc = ESMF_SUCCESS + + call ESMF_VMGetCurrent(vm, rc=rc) + if (ESMF_LogFoundError(rc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + + call ESMF_VMGet(vm, localpet =lpet, petcount=npet, rc=rc) + if (ESMF_LogFoundError(rc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + + call ESMF_ClockGet(clock, currTime=currTime, alarmCount=alarmCount, rc=rc) + if (ESMF_LogFoundError(rc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + + if(lpet == 0) then + write(*, '(A, A)') 'Clock Debug Printout: ', name + write(*, *) '' + write(*, *) 'AlarmCount = ', alarmCount + call ESMF_TimeDebug(currTime, 'currTime', rc=rc) + endif +end subroutine ESMF_ClockDebug end module ESMF_ClockMod diff --git a/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C b/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C index bc9618d2a5..4f6110a49b 100644 --- a/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C +++ b/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C @@ -154,6 +154,8 @@ int Alarm::count=0; alarm->stopTime = *stopTime; } if (ringDuration != ESMC_NULL_POINTER) { + ESMC_LogDefault.Write("ringDuration is no longer supported. Please contact ESMF support.", + ESMC_LOGMSG_WARN, ESMC_CONTEXT); alarm->ringDuration = *ringDuration; } if (ringTimeStepCount != ESMC_NULL_POINTER) { @@ -477,7 +479,8 @@ void Alarm::enableSticky(void){ bool *ringing, // out bool *ringingOnPrevTimeStep, // out bool *enabled, // out - bool *sticky) { // out + bool *sticky, // out + bool *ringerIsOn) { // out // // !DESCRIPTION: // Gets {\tt ESMC\_Alarm} property values; @@ -563,6 +566,9 @@ void Alarm::enableSticky(void){ if (sticky != ESMC_NULL_POINTER) { *sticky = this->sticky; } + if (ringerIsOn != ESMC_NULL_POINTER) { + *ringerIsOn = this->ringerIsOn; + } rc = ESMF_SUCCESS; return(rc); @@ -836,9 +842,10 @@ void Alarm::enableSticky(void){ // Initialize return code; assume routine not implemented if (rc != ESMC_NULL_POINTER) *rc = ESMF_SUCCESS; - Time clockTime = clock->currTime; + //Time clockTime = clock->currTime; - return(enabled && ringerIsOn && willRingAtTime(clockTime)); + //return(enabled && ringerIsOn && canRingAtTime(clockTime)); + return(enabled && ringing); } // end Alarm::isRinging @@ -895,7 +902,7 @@ void Alarm::enableSticky(void){ if (rc != ESMC_NULL_POINTER) *rc = ESMF_SUCCESS; Time clockNextTime; clock->Clock::getNextTime(&clockNextTime, timeStep); - return willRingAtTime(clockNextTime); + return canRingAtTime(clockNextTime); } // end Alarm::willRingNext @@ -941,7 +948,7 @@ void Alarm::enableSticky(void){ // get clock's prev time if (rc != ESMC_NULL_POINTER) *rc = ESMF_SUCCESS; Time clockTime = clock->currTime - clock->timeStep; - return willRingAtTime(clockTime); + return canRingAtTime(clockTime); } // end Alarm::wasPrevRinging @@ -1079,25 +1086,12 @@ void Alarm::enableSticky(void){ } // end Alarm::isSticky -#define DEBUG 0 -bool Alarm::willRingAtTime(const Time & clockTime) const{ +#define DEBUG 1 +bool Alarm::canRingAtTime(const Time & clockTime) const{ bool retval = false; - TimeInterval deltaT = clockTime - this->firstRingTime; - - ESMC_R8 rn = deltaT/ringInterval; - - ESMC_I4 n = int(rn); - -#if DEBUG == 1 - printf("number of intervals %f %d \n", rn, n); -#endif - - if( (this->firstRingTime + n *ringInterval == clockTime) || - (this->firstRingTime + (n+1)*ringInterval == clockTime) ) + if(this->ringTime == clockTime) retval = true; - else - retval = false; return retval; } @@ -1142,30 +1136,26 @@ bool Alarm::willRingAtTime(const Time & clockTime) const{ ESMC_LogDefault.Write(logMsg, ESMC_LOGMSG_WARN,ESMC_CONTEXT); return(false); } - if(!ringerIsOn) { - if (rc != ESMC_NULL_POINTER) *rc = ESMF_SUCCESS; - return false; - } - - // If the ringing is controlled by ringer, the following logic is redundant. - - // If the alarm is sticky then whether it's ringing or not is controled - // by ringerOn or ringerOff by user + Time clockTime = clock->currTime; + bool canRing = canRingAtTime( clockTime); // Check if the alarm can ring when time matches. - // If the alarm is sticky and the ringer is turned off, then it cannot ring - // else calculate the ringing state of the alarm. if(sticky) { - if(!ringerIsOn) { - if (rc != ESMC_NULL_POINTER) *rc = ESMF_SUCCESS; - return false; + + /* A sticky alarm can ring for two reasons + * 1) it rang previously + * 2) it didn't ring but now it's the time to ring + */ + if(ringing || canRing){ // Set ringing true either because it's a sticky ringing alarm or time matches. + ringing = true; + if (canRing) updateRingTime(rc); // If the alarm's time match clock time, advance ringTime + return (ringing && enabled); } } - // Otherwise only the current state of the clock and alarm is used - // to determine if the alarm should ring. - Time clockTime = clock->currTime; - if (willRingAtTime( clockTime)){ + // Non-sticky one shot alarms, time must match + if (canRing){ ringing = true; + updateRingTime(rc); // If the alarm's time match clock time, advance ringTime }else{ ringing = false; } @@ -1200,9 +1190,8 @@ bool Alarm::willRingAtTime(const Time & clockTime) const{ if(ringing){ prevRingTime = ringTime; - ringTime = clock->currTime; + ringTime = ringTime + ringInterval; } - } //------------------------------------------------------------------------- diff --git a/src/Infrastructure/TimeMgr/src/ESMCI_Clock.C b/src/Infrastructure/TimeMgr/src/ESMCI_Clock.C index d7b3236555..720e37c001 100644 --- a/src/Infrastructure/TimeMgr/src/ESMCI_Clock.C +++ b/src/Infrastructure/TimeMgr/src/ESMCI_Clock.C @@ -645,7 +645,6 @@ int Clock::count=0; // check each alarm to see if it's time to ring ringing = alarmList[i]->Alarm::checkRingTime(&rc); - if(ringing) alarmList[i]->Alarm::updateRingTime(&rc); // report ringing alarms if requested if (ringing) { From 8fddb324421f0ac7c864681ab38eed3e8e875406 Mon Sep 17 00:00:00 2001 From: Fei Liu Date: Mon, 25 Apr 2022 12:13:27 -0400 Subject: [PATCH 08/32] New alarm implemention with updated tests and examples --- src/Infrastructure/TimeMgr/doc/Alarm_rest.tex | 20 +- .../TimeMgr/examples/ESMF_AlarmEx.F90 | 523 ++- .../TimeMgr/include/ESMCI_Alarm.h | 55 +- .../TimeMgr/include/ESMCI_Clock.h | 6 +- .../TimeMgr/interface/ESMCI_Alarm_F.C | 60 +- .../TimeMgr/interface/ESMF_Alarm.F90 | 75 +- .../TimeMgr/interface/ESMF_Clock.F90 | 27 +- src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C | 256 +- src/Infrastructure/TimeMgr/src/ESMCI_Clock.C | 6 + .../TimeMgr/tests/ESMF_AlarmUTest.F90 | 3426 +++++------------ 10 files changed, 1815 insertions(+), 2639 deletions(-) diff --git a/src/Infrastructure/TimeMgr/doc/Alarm_rest.tex b/src/Infrastructure/TimeMgr/doc/Alarm_rest.tex index 80e17ed337..aca44671c6 100644 --- a/src/Infrastructure/TimeMgr/doc/Alarm_rest.tex +++ b/src/Infrastructure/TimeMgr/doc/Alarm_rest.tex @@ -7,21 +7,11 @@ This constant is defined in both Fortran and C++ with a \#define for ease of modification. -\item {\bf Sticky alarm end times in reverse} For sticky alarms, there is -an implicit limitation that in order to properly reverse timestep through a -ring end time, that time must have already been traversed in the forward -direction. This is due to the fact that the Time Manager cannot predict -when user code will call {\tt ESMF\_AlarmRingerOff()}. An error message -will be logged when this limitation is not satisfied. +\item {\bf Alarm ringInterval } The alarm ring interval must be greater +than or equal to clock time step. This is consistent with physical clock and +alarm behavior. -\item {\bf Sticky alarm ring interval in reverse} -\begin{sloppypar} -For repeating sticky alarms, -it is currently assumed that the ringInterval is constant, so that only the -time of the last call to {\tt ESMF\_AlarmRingerOff()} is saved. In -{\tt ESMF\_DIRECTION\_REVERSE}, this information is used to turn sticky alarms -back on. In a future release, ringIntervals will be allowed to be variable, -by saving alarm state at every timestep. -\end{sloppypar} +\item {\bf Alarm ring time} An alarm will only ring if its ring time matches +exactly the clock's current time. \end{enumerate} diff --git a/src/Infrastructure/TimeMgr/examples/ESMF_AlarmEx.F90 b/src/Infrastructure/TimeMgr/examples/ESMF_AlarmEx.F90 index b8d82480cb..0ecfd27d2e 100644 --- a/src/Infrastructure/TimeMgr/examples/ESMF_AlarmEx.F90 +++ b/src/Infrastructure/TimeMgr/examples/ESMF_AlarmEx.F90 @@ -31,22 +31,23 @@ program ESMF_AlarmEx implicit none ! instantiate time_step, start, stop, and alarm times - type(ESMF_TimeInterval) :: timeStep, alarmInterval - type(ESMF_Time) :: alarmTime, startTime, stopTime + type(ESMF_TimeInterval) :: timeStep, alarmInterval, ringTimeInterval + type(ESMF_Time) :: alarmTime, startTime, stopTime, ringTime + logical :: ringing, enabled, sticky ! instantiate a clock type(ESMF_Clock) :: clock ! instantiate Alarm lists integer, parameter :: NUMALARMS = 2 - type(ESMF_Alarm) :: alarm(NUMALARMS) + type(ESMF_Alarm) :: alarms(NUMALARMS), alarm ! local variables for Get methods integer :: ringingAlarmCount ! at any time step (0 to NUMALARMS) ! name, loop counter, result code character (len=ESMF_MAXSTR) :: name - integer :: i, rc, result + integer :: i, n, nrings, rc, result, status !EOC ! result code @@ -127,7 +128,7 @@ program ESMF_AlarmEx if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) !BOC - alarm(1) = ESMF_AlarmCreate(clock, & + alarms(1) = ESMF_AlarmCreate(clock, & ringTime=alarmTime, name="Example alarm 1", rc=rc) !EOC @@ -149,7 +150,7 @@ program ESMF_AlarmEx !BOC ! Alarm gets default name "Alarm002" - alarm(2) = ESMF_AlarmCreate(clock=clock, ringTime=alarmTime, & + alarms(2) = ESMF_AlarmCreate(clock=clock, ringTime=alarmTime, & ringInterval=alarmInterval, rc=rc) !EOC @@ -189,13 +190,13 @@ program ESMF_AlarmEx print *, "number of ringing alarms = ", ringingAlarmCount do i = 1, NUMALARMS - if (ESMF_AlarmIsRinging(alarm(i), rc=rc)) then + if (ESMF_AlarmIsRinging(alarms(i), rc=rc)) then !EOC if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) !BOC - call ESMF_AlarmGet(alarm(i), name=name, rc=rc) + call ESMF_AlarmGet(alarms(i), name=name, rc=rc) print *, trim(name), " is ringing!" !EOC @@ -203,7 +204,7 @@ program ESMF_AlarmEx !BOC ! after processing alarm, turn it off - call ESMF_AlarmRingerOff(alarm(i), rc=rc) + call ESMF_AlarmRingerOff(alarms(i), rc=rc) !EOC if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) @@ -215,6 +216,7 @@ program ESMF_AlarmEx end do ! timestep clock !EOC +!------------------------------------------------------------------------------ !BOE !\subsubsection{Alarm and Clock destruction} @@ -222,13 +224,13 @@ program ESMF_AlarmEx !EOE !BOC - call ESMF_AlarmDestroy(alarm(1), rc=rc) + call ESMF_AlarmDestroy(alarms(1), rc=rc) !EOC if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) !BOC - call ESMF_AlarmDestroy(alarm(2), rc=rc) + call ESMF_AlarmDestroy(alarms(2), rc=rc) !EOC if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) @@ -239,6 +241,505 @@ program ESMF_AlarmEx if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) +!------------------------------------------------------------------------------ +!------------------------------------------------------------------------------ +!------------------------------------------------------------------------------ + +!BOE +!\subsubsection{One shot Alarm} + +! This example shows how to set up an one shot alarm that will ring exactly at +! the ringtime specified during alarmCreate but not at any other time. +! +! To specify such an alarm, do not use the ringInterval argument during AlarmCreate. +!EOE +!BOE + +! A clock is set up to run from 0h0m0s to 1h0m0s; One shot ring time is set to 0h30m0s. + +!EOE +!BOC + call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() +!BOC + call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() +!BOC + call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=30,s=0,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + +!BOE + +! The clock advances by 10 minutes. + +!EOE +!BOC + call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + nrings = 0 +!BOE + +! Create the clock from the specified start time, stop time and time step. + +!EOE +!BOC + clock = ESMF_ClockCreate(timeStep=timeStep,startTime=startTime,stopTime=stopTime,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() +!BOE + +! Create the alarm from the specified ring time (0h0m0s) only. This is how one shot alarm +! is created. +! This alarm is enabled upon creation and non sticky. + +!EOE +!BOC + alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, enabled=.true., sticky=.false., name='alarm', rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + +!BOE + +! Query the alarm to check if it's ringing, enabled and sticky. In this case, we expect +! the alarm to return ringing=true, enabled=true, sticky=false. + +!EOE +!BOC + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + !print *, 'Ex: ringing = ', ringing +!BOE + +! Advance the clock 6 times to move from 0h0m0s to 1h0m0s. + +!EOE +!BOC + do n = 1, 6 + call ESMF_ClockAdvance(clock,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() +!BOE + +! Query the alarm to check if it's ringing, enabled and sticky. In this case, we expect +! the alarm only return ringing=true at 0h 30m 0s. + +!EOE +!BOC + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + !print *, ' Ex: ringing = ', ringing + enddo + +!BOE + +! Destroy the alarm and clock created for this example. + +!EOE +!BOC + call ESMF_AlarmDestroy(alarm, rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() +!BOC + call ESMF_ClockDestroy(clock, rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + +!------------------------------------------------------------------------------ +!------------------------------------------------------------------------------ +!------------------------------------------------------------------------------ +!BOE +!\subsubsection{Using Alarm in clock running forward} + +! This example shows how to set up an alarm in conjuction with a reverse +! running clock. +!EOE +!BOE + +! A clock is set up to run from 0h0m0s to 1h0m0s; Initial ring time is set to 0h0m0s. + +!EOE +!BOC + call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() +!BOC + call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() +!BOC + call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + +!BOE + +! The clock advances by 10 minutes and the alarm rings every 10 minutes as well. + +!EOE +!BOC + call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() +!BOC + call ESMF_TimeIntervalSet(ringTimeInterval,S=600, sN=0, sD=1,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + nrings = 0 +!BOE + +! Create the clock from the specified start time, stop time and time step. + +!EOE +!BOC + clock = ESMF_ClockCreate(timeStep=timeStep,startTime=startTime,stopTime=stopTime,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() +!BOE + +! Create the alarm from the specified ring time (0h0m0s), ring interval (10 minutes). +! This alarm is enabled upon creation and non sticky. + +!EOE +!BOC + alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, ringInterval=ringTimeInterval, enabled=.true., sticky=.false., name='alarm', rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + +!BOE + +! Query the alarm to check if it's ringing, enabled and sticky. In this case, we expect +! the alarm to return ringing=true, enabled=true, sticky=false. + +!EOE +!BOC + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + if(ringing) nrings = nrings + 1 + !print *, 'Ex: ringing = ', ringing +!BOE + +! Advance the clock 6 times to move from 0h0m0s to 1h0m0s. + +!EOE +!BOC + do n = 1, 6 + call ESMF_ClockAdvance(clock,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() +!BOE + +! Query the alarm to check if it's ringing, enabled and sticky. In this case, we expect +! the alarm should return ringing=true, enabled=true, sticky=false every clock time step +! because the alarm and the clock have identical time step (or interval). + +!EOE +!BOC + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + !print *, ' Ex: ringing = ', ringing + if(ringing) nrings = nrings + 1 + enddo + +!BOE + +! Destroy the alarm and clock created for this example. + +!EOE +!BOC + call ESMF_AlarmDestroy(alarm, rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() +!BOC + call ESMF_ClockDestroy(clock, rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + +!------------------------------------------------------------------------------ +!------------------------------------------------------------------------------ +!------------------------------------------------------------------------------ +!BOE +!\subsubsection{Using Alarm in clock running reverse} + +! This example shows how to set up an alarm in conjuction with a reverse +! running clock. +!EOE +!BOE + +! A clock is set up to run from 1h0m0s to 0h0m0s; Initial ring time is set to 1h0m0s. +! For clock running in reverse direction, the start time should still be in the past +! compared with the stoptime. This example shows the start time is 0h0m0s, the stop +! time is 1h0m0s. We will set the current time to 1h0m0s and set the clock to run +! in reverse direction. + +!EOE +!BOC + call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() +!BOC + call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() +!BOC + call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + +!BOE + +! The clock advances by 10 minutes and the alarm rings every 10 minutes as well. + +!EOE +!BOC + call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() +!BOC + call ESMF_TimeIntervalSet(ringTimeInterval,S=600, sN=0, sD=1,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + nrings = 0 +!BOE + +! Create the clock from the specified start time, stop time and time step. + +!EOE +!BOC + clock = ESMF_ClockCreate(timeStep=timeStep,startTime=startTime,stopTime=stopTime,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() +!BOE + +! Here we set the current time on the clock to stop time 1h0m0s and set the clock to run in +! reverse direction. + +!EOE + +!BOC + call ESMF_ClockSet(clock, currTime = stopTime, direction=ESMF_DIRECTION_REVERSE, rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() +!BOE + +! Create the alarm from the specified ring time (0h0m0s), ring interval (10 minutes). +! This alarm is enabled upon creation and non sticky. + +!EOE +!BOC + alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, ringInterval=ringTimeInterval, enabled=.true., sticky=.false., name='alarm', rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + +!BOE + +! Query the alarm to check if it's ringing, enabled and sticky. In this case, we expect +! the alarm to return ringing=true, enabled=true, sticky=false. + +!EOE +!BOC + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + if(ringing) nrings = nrings + 1 + !print *, 'Ex: ringing = ', ringing +!BOE + +! Advance the clock 6 times to move from 0h0m0s to 1h0m0s. + +!EOE +!BOC + do n = 1, 6 + call ESMF_ClockAdvance(clock,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() +!BOE + +! Query the alarm to check if it's ringing, enabled and sticky. In this case, we expect +! the alarm should return ringing=true, enabled=true, sticky=false every clock time step +! because the alarm and the clock have identical time step (or interval). + +!EOE +!BOC + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + !print *, ' Ex: ringing = ', ringing + if(ringing) nrings = nrings + 1 + enddo + +!BOE + +! Destroy the alarm and clock created for this example. + +!EOE +!BOC + call ESMF_AlarmDestroy(alarm, rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() +!BOC + call ESMF_ClockDestroy(clock, rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + +!------------------------------------------------------------------------------ +!------------------------------------------------------------------------------ +!------------------------------------------------------------------------------ +!BOE +!\subsubsection{Using Alarm in clock runs forward then reverse} + +! This example shows how to set up an alarm in conjuction with a reverse +! running clock. +!EOE + +!BOE + +! A clock is set up to run from 0h0m0s to 1h0m0s; Initial ring time is set to 0h0m0s. + +!EOE +!BOC + call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() +!BOC + call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() +!BOC + call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + +!BOE + +! The clock advances by 10 minutes and the alarm rings every 10 minutes as well. + +!EOE +!BOC + call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() +!BOC + call ESMF_TimeIntervalSet(ringTimeInterval,S=600, sN=0, sD=1,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + nrings = 0 +!BOE + +! Create the clock from the specified start time, stop time and time step. + +!EOE +!BOC + clock = ESMF_ClockCreate(timeStep=timeStep,startTime=startTime,stopTime=stopTime,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() +!BOE + +! Create the alarm from the specified ring time (0h0m0s), ring interval (10 minutes). +! This alarm is enabled upon creation and non sticky. + +!EOE +!BOC + alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, ringInterval=ringTimeInterval, enabled=.true., sticky=.false., name='alarm', rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + +!BOE + +! Query the alarm to check if it's ringing, enabled and sticky. In this case, we expect +! the alarm to return ringing=true, enabled=true, sticky=false. + +!EOE +!BOC + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + if(ringing) nrings = nrings + 1 + !print *, 'Ex: ringing = ', ringing +!BOE + +! Advance the clock 6 times to move from 0h0m0s to 1h0m0s. + +!EOE +!BOC + do n = 1, 6 + call ESMF_ClockAdvance(clock,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() +!BOE + +! Query the alarm to check if it's ringing, enabled and sticky. In this case, we expect +! the alarm should return ringing=true, enabled=true, sticky=false every clock time step +! because the alarm and the clock have identical time step (or interval). + +!EOE +!BOC + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + !print *, ' Ex: ringing = ', ringing + if(ringing) nrings = nrings + 1 + enddo +!BOE + +! Reverse the direction of the clock, since the clock's current time is 1h0m0s, the clock +! now runs backward to 0h50m0s, 0h40m0s, etc. + +!EOE +!BOC + call ESMF_ClockSet(clock, direction = ESMF_DIRECTION_REVERSE, rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() +!BOE + +! Advance the clock 6 times to move from 1h0m0s to 0h0m0s. + +!EOE +!BOC + do n = 1, 6 + call ESMF_ClockAdvance(clock,rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() +!BOE + +! Query the alarm to check if it's ringing, enabled and sticky. In this case, we expect +! the alarm should return ringing=true, enabled=true, sticky=false every clock time step +! because the alarm and the clock have identical time step (or interval). + +!EOE +!BOC + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + if(ringing) nrings = nrings + 1 + !print *, ' Ex: ringing = ', ringing + enddo +!BOE + +! Destroy the alarm and clock created for this example. + +!EOE +!BOC + call ESMF_AlarmDestroy(alarm, rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() +!BOC + call ESMF_ClockDestroy(clock, rc=status) +!EOC + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + ! IMPORTANT: ESMF_STest() prints the PASS string and the # of processors in the log ! file that the scripts grep for. call ESMF_STest((finalrc.eq.ESMF_SUCCESS), testname, failMsg, result, ESMF_SRCLINE) diff --git a/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h b/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h index 6c27ea821f..ce0d0ca3ed 100644 --- a/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h +++ b/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h @@ -28,6 +28,7 @@ #include "ESMCI_Util.h" #include "ESMCI_Macros.h" #include "ESMF_TimeMgr.inc" +#include //------------------------------------------------------------------------- //BOP @@ -165,35 +166,22 @@ class Alarm { // accessor methods - int set(int nameLen, + int set(int nameLen, const char *name=0, - Clock **clock=0, - Time *ringTime=0, - TimeInterval *ringInterval=0, - Time *stopTime=0, - TimeInterval *ringDuration=0, - int *ringTimeStepCount=0, - Time *refTime=0, + Clock **clock=0, + Time *ringTime=0, + TimeInterval *ringInterval=0, bool *ringing=0, bool *enabled=0, // (TMG 4.1, 4.7) bool *sticky=0); - int get(int nameLen, + int get(int nameLen, int *tempNameLen, char *tempName=0, - Clock **clock=0, - Time *ringTime=0, - Time *prevRingTime=0, - TimeInterval *ringInterval=0, - Time *stopTime=0, - TimeInterval *ringDuration=0, - int *ringTimeStepCount=0, - int *timeStepRingingCount=0, - Time *ringBegin=0, - Time *ringEnd=0, - Time *refTime=0, + Clock **clock=0, + Time *ringTime=0, + TimeInterval *ringInterval=0, bool *ringing=0, - bool *ringingOnPrevTimeStep=0, bool *enabled=0, // (TMG 4.1, 4.7) bool *sticky=0, bool *ringerIsOn=0); @@ -221,6 +209,7 @@ class Alarm { // negative direction // Can be basis for asynchronous alarm reporting void updateRingTime(int *rc=0); + void clockChangeDirection(const ESMC_Direction & old_direction, const ESMC_Direction & new_direction, int *rc=0); bool operator==(const Alarm &) const; bool operator!=(const Alarm &) const; @@ -249,8 +238,7 @@ class Alarm { // friend to allocate and initialize alarm from heap friend Alarm *ESMCI_alarmCreate(int, const char*, Clock*, - Time*, TimeInterval*, Time*, - TimeInterval*, int*, Time*, bool*, + Time*, TimeInterval*, bool*, bool*, int*); // friend function to copy an alarm @@ -278,16 +266,25 @@ class Alarm { // enable Sticky void enableSticky(void); - bool canRingAtTime(const Time & clockTime) const; + bool canRingAtTime(const Clock & clock) ; + bool canRingAtNextTime(Clock & clock, TimeInterval *timeStep) const; // friend class alarm friend class Clock; + // Keep track of 2 states for ringing calculation + // 0: saved current, 1: previous, 2, previous-previous .... + // saved current becomes previous, current becomes saved current as state evolves. + // It's possible to have more saved previous states + std::vector alarms; + std::vector clocks; // //EOP //------------------------------------------------------------------------- }; // end class Alarm + const int SAVEDCURRENT=0; + const int SAVESIZE=2; // Note: though seemingly redundant with the friend declarations within // the class definition above, the following declarations are necessary @@ -296,13 +293,9 @@ class Alarm { Alarm *ESMCI_alarmCreate(int nameLen, const char* name=0, - Clock* clock=0, - Time* ringTime=0, - TimeInterval* ringInterval=0, - Time* stopTime=0, - TimeInterval* ringDuration=0, - int* ringTimeStepCount=0, - Time* refTime=0, + Clock* clock=0, + Time* ringTime=0, + TimeInterval* ringInterval=0, bool* enabled=0, bool* sticky=0, int* rc=0); diff --git a/src/Infrastructure/TimeMgr/include/ESMCI_Clock.h b/src/Infrastructure/TimeMgr/include/ESMCI_Clock.h index 8bff713880..e5a91ec925 100644 --- a/src/Infrastructure/TimeMgr/include/ESMCI_Clock.h +++ b/src/Infrastructure/TimeMgr/include/ESMCI_Clock.h @@ -197,7 +197,7 @@ namespace ESMCI{ int syncToRealTime(void); // TMG3.4.5 // (see Time::SyncToRealTime() - // to suuport copying of the alarmList + // to support copying of the alarmList Clock& operator=(const Clock &); bool operator==(const Clock &) const; @@ -241,8 +241,8 @@ namespace ESMCI{ // friend to allocate and initialize alarm from heap // (needs access to clock current time to initialize alarm ring time) friend Alarm *ESMCI_alarmCreate(int, const char*, Clock*, - Time*, TimeInterval*, Time*, - TimeInterval*, int*, Time*, bool*, + Time*, + TimeInterval*, bool*, bool*, int*); // friend function to copy an alarm diff --git a/src/Infrastructure/TimeMgr/interface/ESMCI_Alarm_F.C b/src/Infrastructure/TimeMgr/interface/ESMCI_Alarm_F.C index 627f808a7f..47632a6ef8 100644 --- a/src/Infrastructure/TimeMgr/interface/ESMCI_Alarm_F.C +++ b/src/Infrastructure/TimeMgr/interface/ESMCI_Alarm_F.C @@ -41,8 +41,6 @@ extern "C" { void FTN_X(c_esmc_alarmcreatenew)(Alarm **ptr, int *nameLen, const char *name, Clock **clock, Time *ringTime, TimeInterval *ringInterval, - Time *stopTime, TimeInterval *ringDuration, - int *ringTimeStepCount, Time *refTime, bool *enabled, bool *sticky, int *status, ESMCI_FortranStrLenArg name_l) { *ptr = ESMCI_alarmCreate( @@ -52,10 +50,6 @@ extern "C" { *clock, // required. ESMC_NOT_PRESENT_FILTER(ringTime), ESMC_NOT_PRESENT_FILTER(ringInterval), - ESMC_NOT_PRESENT_FILTER(stopTime), - ESMC_NOT_PRESENT_FILTER(ringDuration), - ESMC_NOT_PRESENT_FILTER(ringTimeStepCount), - ESMC_NOT_PRESENT_FILTER(refTime), ESMC_NOT_PRESENT_FILTER(enabled), ESMC_NOT_PRESENT_FILTER(sticky), ESMC_NOT_PRESENT_FILTER(status) ); @@ -77,8 +71,6 @@ extern "C" { void FTN_X(c_esmc_alarmset)(Alarm **ptr, int *nameLen, const char *name, Clock **clock, Time *ringTime, TimeInterval *ringInterval, - Time *stopTime, TimeInterval *ringDuration, - int *ringTimeStepCount, Time *refTime, bool *ringing, bool *enabled, bool *sticky, int *status, ESMCI_FortranStrLenArg name_l) { @@ -90,28 +82,33 @@ extern "C" { ESMC_NOT_PRESENT_FILTER(clock), ESMC_NOT_PRESENT_FILTER(ringTime), ESMC_NOT_PRESENT_FILTER(ringInterval), - ESMC_NOT_PRESENT_FILTER(stopTime), - ESMC_NOT_PRESENT_FILTER(ringDuration), - ESMC_NOT_PRESENT_FILTER(ringTimeStepCount), - ESMC_NOT_PRESENT_FILTER(refTime), ESMC_NOT_PRESENT_FILTER(ringing), ESMC_NOT_PRESENT_FILTER(enabled), ESMC_NOT_PRESENT_FILTER(sticky) ); if (ESMC_PRESENT(status)) *status = rc; } + int get(int nameLen, + int *tempNameLen, + char *tempName=0, + Clock **clock=0, + Time *ringTime=0, + TimeInterval *ringInterval=0, + bool *ringing=0, + bool *enabled=0, // (TMG 4.1, 4.7) + bool *sticky=0, + bool *ringerIsOn=0); void FTN_X(c_esmc_alarmget)(Alarm **ptr, int *nameLen, int *tempNameLen, char *tempName, Clock **clock, - Time *ringTime, Time *prevRingTime, - TimeInterval *ringInterval, Time *stopTime, - TimeInterval *ringDuration, int *ringTimeStepCount, - int *timeStepRingingCount, Time *ringBegin, - Time *ringEnd, Time *refTime, bool *ringing, - bool *ringingOnPrevTimeStep, bool *enabled, bool *sticky, bool *ringerIsOn, + Time *ringTime, + TimeInterval *ringInterval, + bool *ringing, + bool *enabled, bool *sticky, bool *ringerIsOn, int *status, ESMCI_FortranStrLenArg tempName_l) { ESMF_CHECK_POINTER(*ptr, status) + //if(sticky != 0) printf("ptr address %x => %d \n", sticky, (int)*sticky); int rc = (*ptr)->Alarm::get( // always presnet internal arguments *nameLen, @@ -119,20 +116,29 @@ extern "C" { tempName, ESMC_NOT_PRESENT_FILTER(clock), ESMC_NOT_PRESENT_FILTER(ringTime), - ESMC_NOT_PRESENT_FILTER(prevRingTime), ESMC_NOT_PRESENT_FILTER(ringInterval), - ESMC_NOT_PRESENT_FILTER(stopTime), - ESMC_NOT_PRESENT_FILTER(ringDuration), - ESMC_NOT_PRESENT_FILTER(ringTimeStepCount), - ESMC_NOT_PRESENT_FILTER(timeStepRingingCount), - ESMC_NOT_PRESENT_FILTER(ringBegin), - ESMC_NOT_PRESENT_FILTER(ringEnd), - ESMC_NOT_PRESENT_FILTER(refTime), ESMC_NOT_PRESENT_FILTER(ringing), - ESMC_NOT_PRESENT_FILTER(ringingOnPrevTimeStep), ESMC_NOT_PRESENT_FILTER(enabled), ESMC_NOT_PRESENT_FILTER(sticky), ESMC_NOT_PRESENT_FILTER(ringerIsOn) ); + if(sticky != 0) { + if(*sticky) *(int *)sticky = 1; + else *(int *)sticky = 0; + //printf("ptr address %x => %d \n", sticky, *(int *)sticky); + } + if(ringing != 0) { + if(*ringing) *(int *)ringing = 1; + else *(int *)ringing = 0; + //printf("ptr address %x => %d \n", ringing, *(int *)ringing); + } + if(enabled != 0) { + if(*enabled) *(int *)enabled = 1; + else *(int *)enabled = 0; + } + if(ringerIsOn != 0) { + if(*ringerIsOn) *(int *)ringerIsOn = 1; + else *(int *)ringerIsOn = 0; + } if (ESMC_PRESENT(status)) *status = rc; } diff --git a/src/Infrastructure/TimeMgr/interface/ESMF_Alarm.F90 b/src/Infrastructure/TimeMgr/interface/ESMF_Alarm.F90 index 1ee7b10823..db2a8ee37c 100644 --- a/src/Infrastructure/TimeMgr/interface/ESMF_Alarm.F90 +++ b/src/Infrastructure/TimeMgr/interface/ESMF_Alarm.F90 @@ -296,8 +296,8 @@ module ESMF_AlarmMod ! !INTERFACE: ! Private name; call using ESMF_AlarmCreate() function ESMF_AlarmCreateNew(clock, keywordEnforcer, & - ringTime, ringInterval, stopTime, ringDuration, ringTimeStepCount, & - refTime, enabled, sticky, name, rc) + ringTime, ringInterval, & + enabled, sticky, name, rc) ! !RETURN VALUE: type(ESMF_Alarm) :: ESMF_AlarmCreateNew @@ -307,10 +307,6 @@ function ESMF_AlarmCreateNew(clock, keywordEnforcer, & type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below type(ESMF_Time), intent(in), optional :: ringTime type(ESMF_TimeInterval), intent(in), optional :: ringInterval - type(ESMF_Time), intent(in), optional :: stopTime - type(ESMF_TimeInterval), intent(in), optional :: ringDuration - integer, intent(in), optional :: ringTimeStepCount - type(ESMF_Time), intent(in), optional :: refTime logical, intent(in), optional :: enabled logical, intent(in), optional :: sticky character (len=*), intent(in), optional :: name @@ -342,27 +338,6 @@ function ESMF_AlarmCreateNew(clock, keywordEnforcer, & ! {\tt ringTime} is not also specified (first ring time), it will be ! calculated as the {\tt clock}'s current time plus {\tt ringInterval}. ! Must specify at least one of ringTime or ringInterval. -! \item[{[stopTime]}] -! The stop time for repeating (interval) alarms. If not -! specified, an interval alarm will repeat forever. -! \item[{[ringDuration]}] -! The absolute ring duration. If not sticky (see argument below), -! alarms rings for ringDuration, then turns itself off. Default is -! zero (unused). Mutually exclusive with ringTimeStepCount (below); -! used only if set to a non-zero duration and ringTimeStepCount is 1 -! (see below). -! See also {\tt ESMF\_AlarmSticky()}, {\tt ESMF\_AlarmNotSticky()}. -! \item[{[ringTimeStepCount]}] -! The relative ring duration. If not sticky (see argument below), -! alarms rings for ringTimeStepCount, then turns itself off. -! Default is 1: a non-sticky alarm will ring for one clock time step. -! Mutually exclusive with ringDuration (above); used if -! ringTimeStepCount > 1. If ringTimeStepCount is 1 (default) and -! ringDuration is non-zero, ringDuration is used (see above), otherwise -! ringTimeStepCount is used. -! See also {\tt ESMF\_AlarmSticky()}, {\tt ESMF\_AlarmNotSticky()}. -! \item[{[refTime]}] -! The reference (i.e. base) time for an interval alarm. ! \item[{[enabled]}] ! Sets the enabled state; default is on (true). If disabled, ! an alarm will not function at all. @@ -406,9 +381,6 @@ function ESMF_AlarmCreateNew(clock, keywordEnforcer, & ESMF_INIT_CHECK_DEEP(ESMF_ClockGetInit,clock,rc) ESMF_INIT_CHECK_SHALLOW(ESMF_TimeGetInit,ringTime,rc) ESMF_INIT_CHECK_SHALLOW(ESMF_TimeIntervalGetInit,ringInterval,rc) - ESMF_INIT_CHECK_SHALLOW(ESMF_TimeGetInit,stopTime,rc) - ESMF_INIT_CHECK_SHALLOW(ESMF_TimeIntervalGetInit,ringDuration,rc) - ESMF_INIT_CHECK_SHALLOW(ESMF_TimeGetInit,refTime,rc) ! get length of given name for C++ validation if (present(name)) then @@ -417,8 +389,7 @@ function ESMF_AlarmCreateNew(clock, keywordEnforcer, & ! invoke C to C++ entry point to allocate and initialize new alarm call c_ESMC_AlarmCreateNew(ESMF_AlarmCreateNew, nameLen, name, clock, & - ringTime, ringInterval, stopTime, & - ringDuration, ringTimeStepCount, refTime, & + ringTime, ringInterval, & enabled, sticky, localrc) if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & ESMF_CONTEXT, rcToReturn=rc)) return @@ -660,26 +631,16 @@ end subroutine ESMF_AlarmEnable ! !INTERFACE: subroutine ESMF_AlarmGet(alarm, keywordEnforcer, & - clock, ringTime, prevRingTime, ringInterval, stopTime, ringDuration, & - ringTimeStepCount, timeStepRingingCount, ringBegin, ringEnd, & - refTime, ringing, ringingOnPrevTimeStep, enabled, sticky, ringerIsOn, name, rc) + clock, ringTime, ringInterval, & + ringing, enabled, sticky, ringerIsOn, name, rc) ! !ARGUMENTS: type(ESMF_Alarm), intent(in) :: alarm type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below type(ESMF_Clock), intent(out), optional :: clock type(ESMF_Time), intent(out), optional :: ringTime - type(ESMF_Time), intent(out), optional :: prevRingTime type(ESMF_TimeInterval), intent(out), optional :: ringInterval - type(ESMF_Time), intent(out), optional :: stopTime - type(ESMF_TimeInterval), intent(out), optional :: ringDuration - integer, intent(out), optional :: ringTimeStepCount - integer, intent(out), optional :: timeStepRingingCount - type(ESMF_Time), intent(out), optional :: ringBegin - type(ESMF_Time), intent(out), optional :: ringEnd - type(ESMF_Time), intent(out), optional :: refTime logical, intent(out), optional :: ringing - logical, intent(out), optional :: ringingOnPrevTimeStep logical, intent(out), optional :: enabled logical, intent(out), optional :: sticky logical, intent(out), optional :: ringerIsOn @@ -783,10 +744,8 @@ subroutine ESMF_AlarmGet(alarm, keywordEnforcer, & ! invoke C to C++ entry point call c_ESMC_AlarmGet(alarm, nameLen, tempNameLen, tempName, clock, & - ringTime, prevRingTime, ringInterval, stopTime, & - ringDuration, ringTimeStepCount, & - timeStepRingingCount, ringBegin, ringEnd, refTime, & - ringing, ringingOnPrevTimeStep, enabled, sticky, ringerIsOn, localrc) + ringTime, ringInterval, & + ringing, enabled, sticky, ringerIsOn, localrc) if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & ESMF_CONTEXT, rcToReturn=rc)) return @@ -799,13 +758,7 @@ subroutine ESMF_AlarmGet(alarm, keywordEnforcer, & ! mark outputs as successfully initialized call ESMF_ClockSetInitCreated(clock) call ESMF_TimeInit(ringTime) - call ESMF_TimeInit(prevRingTime) call ESMF_TimeIntervalInit(ringInterval) - call ESMF_TimeInit(stopTime) - call ESMF_TimeIntervalInit(ringDuration) - call ESMF_TimeInit(ringBegin) - call ESMF_TimeInit(ringEnd) - call ESMF_TimeInit(refTime) ! Return success if (present(rc)) rc = ESMF_SUCCESS @@ -1344,8 +1297,8 @@ end subroutine ESMF_AlarmRingerOn ! !INTERFACE: subroutine ESMF_AlarmSet(alarm, keywordEnforcer, & - clock, ringTime, ringInterval, stopTime, ringDuration, & - ringTimeStepCount, refTime, ringing, enabled, sticky, name, rc) + clock, ringTime, ringInterval, & + ringing, enabled, sticky, name, rc) ! !ARGUMENTS: type(ESMF_Alarm), intent(inout) :: alarm @@ -1353,10 +1306,6 @@ subroutine ESMF_AlarmSet(alarm, keywordEnforcer, & type(ESMF_Clock), intent(in), optional :: clock type(ESMF_Time), intent(in), optional :: ringTime type(ESMF_TimeInterval), intent(in), optional :: ringInterval - type(ESMF_Time), intent(in), optional :: stopTime - type(ESMF_TimeInterval), intent(in), optional :: ringDuration - integer, intent(in), optional :: ringTimeStepCount - type(ESMF_Time), intent(in), optional :: refTime logical, intent(in), optional :: ringing logical, intent(in), optional :: enabled logical, intent(in), optional :: sticky @@ -1450,9 +1399,6 @@ subroutine ESMF_AlarmSet(alarm, keywordEnforcer, & ESMF_INIT_CHECK_DEEP(ESMF_ClockGetInit,clock,rc) ESMF_INIT_CHECK_SHALLOW(ESMF_TimeGetInit,ringTime,rc) ESMF_INIT_CHECK_SHALLOW(ESMF_TimeIntervalGetInit,ringInterval,rc) - ESMF_INIT_CHECK_SHALLOW(ESMF_TimeGetInit,stopTime,rc) - ESMF_INIT_CHECK_SHALLOW(ESMF_TimeIntervalGetInit,ringDuration,rc) - ESMF_INIT_CHECK_SHALLOW(ESMF_TimeGetInit,refTime,rc) ! get length of given name for C++ validation if (present(name)) then @@ -1461,8 +1407,7 @@ subroutine ESMF_AlarmSet(alarm, keywordEnforcer, & ! invoke C to C++ entry point call c_ESMC_AlarmSet(alarm, nameLen, name, clock, ringTime, & - ringInterval, stopTime, ringDuration, & - ringTimeStepCount, refTime, ringing, & + ringInterval, ringing, & enabled, sticky, localrc) if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & ESMF_CONTEXT, rcToReturn=rc)) return diff --git a/src/Infrastructure/TimeMgr/interface/ESMF_Clock.F90 b/src/Infrastructure/TimeMgr/interface/ESMF_Clock.F90 index ff57c98bd5..0ffb2c0a34 100644 --- a/src/Infrastructure/TimeMgr/interface/ESMF_Clock.F90 +++ b/src/Infrastructure/TimeMgr/interface/ESMF_Clock.F90 @@ -2117,12 +2117,12 @@ subroutine ESMF_TimeDebug(Time, name, rc) if (ESMF_LogFoundError(rc, ESMF_ERR_PASSTHRU, & ESMF_CONTEXT, rcToReturn=rc)) return - call ESMF_TimeGet(Time, yy=yy, mm=mm, dd=dd, d=d, h=h, m=m, s=s, rc=rc) + call ESMF_TimeGet(Time, yy=yy, mm=mm, dd=dd, h=h, m=m, s=s, rc=rc) if (ESMF_LogFoundError(rc, ESMF_ERR_PASSTHRU, & ESMF_CONTEXT, rcToReturn=rc)) return if(lpet == 0) then - write(*, '(A, A, 3I4, I10, 3I4)') 'Time Debug Printout: ', name, yy, mm, dd, d, h, m, s + write(*, '(A, A, 6I4)') 'Time Debug Printout: ', name, yy, mm, dd, h, m, s endif end subroutine ESMF_TimeDebug @@ -2136,9 +2136,9 @@ subroutine ESMF_AlarmDebug(alarm, name, rc) type (ESMF_VM) :: vm integer :: lpet, npet - logical :: ringing, enabled, sticky, ringingOnPrevTimeStep, ringerIsOn - type (ESMF_Time) :: ringTime, refTime, prevRingTime, stopTime, ringBegin, ringEnd, ringRef - type (ESMF_TimeInterval) :: ringInterval, ringDuration + logical :: ringing, enabled, sticky, ringerIsOn + type (ESMF_Time) :: ringTime + type (ESMF_TimeInterval) :: ringInterval rc = ESMF_SUCCESS @@ -2156,26 +2156,19 @@ subroutine ESMF_AlarmDebug(alarm, name, rc) ringerIsOn = .false. call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, ringerIsOn=ringerIsOn, & - ringTime=ringTime, refTime=refTime, stopTime=stopTime, ringBegin=ringBegin, ringEnd=ringEnd, & - ringInterval=ringInterval, ringDuration=ringDuration, rc=rc) + ringTime=ringTime, ringInterval=ringInterval, rc=rc) if (ESMF_LogFoundError(rc, ESMF_ERR_PASSTHRU, & ESMF_CONTEXT, rcToReturn=rc)) return if(lpet == 0) then write(*, '(A,A)') 'Alarm Debug Printout: ', name - print *, '' print *, 'ringing = ', ringing print *, 'enabled = ', enabled print *, 'sticky = ' , sticky print *, 'ringerIsOn = ' , ringerIsOn - call ESMF_TimeDebug(ringTime, 'ringTime', rc=rc) - call ESMF_TimeDebug(refTime, 'refTime', rc=rc) - !call ESMF_TimeDebug(stopTime, 'stopTime', rc=rc) - !call ESMF_TimeDebug(ringBegin, 'ringBegin', rc=rc) - !call ESMF_TimeDebug(ringEnd, 'ringEnd', rc=rc) + call ESMF_TimeDebug(ringTime, ' ringTime = ', rc=rc) call ESMF_TimeIntervalDebug(ringInterval, 'ringInterval', rc=rc) - call ESMF_TimeIntervalDebug(ringDuration, 'ringDuration', rc=rc) - + print *, '' endif end subroutine ESMF_AlarmDebug @@ -2206,9 +2199,9 @@ subroutine ESMF_ClockDebug(clock, name, rc) if(lpet == 0) then write(*, '(A, A)') 'Clock Debug Printout: ', name - write(*, *) '' write(*, *) 'AlarmCount = ', alarmCount - call ESMF_TimeDebug(currTime, 'currTime', rc=rc) + call ESMF_TimeDebug(currTime, ' currTime = ', rc=rc) + write(*, *) '' endif end subroutine ESMF_ClockDebug diff --git a/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C b/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C index 4f6110a49b..5ae986f83b 100644 --- a/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C +++ b/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C @@ -27,9 +27,12 @@ #include #include #include +#include #include "ESMCI_LogErr.h" #include "ESMCI_Clock.h" +#include "ESMCI_Util.h" +#include "ESMCI_Macros.h" //------------------------------------------------------------------------- // leave the following line as-is; it will insert the cvs ident string @@ -64,13 +67,9 @@ int Alarm::count=0; // !ARGUMENTS: int nameLen, // in const char *name, // in - Clock *clock, // in - Time *ringTime, // in - TimeInterval *ringInterval, // in - Time *stopTime, // in - TimeInterval *ringDuration, // in - int *ringTimeStepCount, // in - Time *refTime, // in + Clock *clock, // in + Time *ringTime, // in + TimeInterval *ringInterval, // in bool *enabled, // in bool *sticky, // in int *rc ) { // out - return code @@ -133,6 +132,34 @@ int Alarm::count=0; alarm->ringTime = alarm->prevRingTime = alarm->firstRingTime = *ringTime; } if (ringInterval != ESMC_NULL_POINTER) { + TimeInterval zeroTimeInterval(0,0,1,0,0,0); + if(*ringInterval < zeroTimeInterval){ + ESMC_LogDefault.MsgFoundError(ESMC_RC_ARG_BAD, + "; Cannot set negative ringInterval", ESMC_CONTEXT, rc); + return 0; + } + + if(*ringInterval < clock->timeStep) { + ESMC_LogDefault.MsgFoundError(ESMC_RC_ARG_BAD, + "; alarm Interval cannot be less than clock interval", ESMC_CONTEXT, rc); + return 0; + } + + if( ( *ringInterval == clock->timeStep) ){ + int n = (*ringTime - clock->currTime)/(*ringInterval); + //std::cout << n << std::endl; + //ringTime->print(); + //clock->currTime.print(); + //ringInterval->print(); + if(*ringTime != (clock->currTime + n*(*ringInterval)) ){ + ESMC_LogDefault.MsgFoundError(ESMC_RC_ARG_BAD, + "; alarm Interval is the same as clock interval, ringTime cannot be misaligned with clock time, alarm will never ring", ESMC_CONTEXT, rc); + return 0; + } + } + + // We do not check LCM because any two rational numbers are guranteed to have + // LCM albeit it may be very large. alarm->ringInterval = *ringInterval; // if ringTime not specified, calculate @@ -143,31 +170,20 @@ int Alarm::count=0; if (ringTime == ESMC_NULL_POINTER) { // works for positive or negative ringInterval - alarm->ringTime = clock->currTime + alarm->ringInterval; + if(clock->direction == ESMF_DIRECTION_FORWARD) + alarm->ringTime = clock->currTime + alarm->ringInterval; + else + alarm->ringTime = clock->currTime - alarm->ringInterval; alarm->prevRingTime = alarm->firstRingTime = alarm->ringTime; } }else{ - alarm->ringInterval = clock->timeStep; + // A negative ringInterval indicates a one shot alarm at ringTime only + TimeInterval zeroTimeInterval(0,0,1,0,0,0); + if(clock->timeStep < zeroTimeInterval) + alarm->ringInterval = clock->timeStep; + alarm->ringInterval = -clock->timeStep; } - if (stopTime != ESMC_NULL_POINTER) { - alarm->stopTime = *stopTime; - } - if (ringDuration != ESMC_NULL_POINTER) { - ESMC_LogDefault.Write("ringDuration is no longer supported. Please contact ESMF support.", - ESMC_LOGMSG_WARN, ESMC_CONTEXT); - alarm->ringDuration = *ringDuration; - } - if (ringTimeStepCount != ESMC_NULL_POINTER) { - alarm->ringTimeStepCount = *ringTimeStepCount; - } - if (refTime != ESMC_NULL_POINTER) { - alarm->refTime = *refTime; - // TODO: for ringInterval, calculate 1st ringTime > clock->currTime, - // (&& > ringTime, if specified), using refTime as the base. - } else { - // TODO: default to clock's current time (or ringTime, if specified?) - } if (enabled != ESMC_NULL_POINTER) { alarm->enabled = *enabled; } @@ -197,6 +213,26 @@ int Alarm::count=0; ESMC_LogDefault.MsgFoundError(returnCode, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc); } +// std::vector::iterator it = alarms.begin(); +// while (it++ != alarms.end()){ +// *it = *this; +// } + +// for (auto it = begin (alarms); it != end (alarms); ++it) { +// *it = *this; +// } + for (int i = 0; i < SAVESIZE; i ++){ + alarm->alarms.push_back(*alarm); + alarm->clocks.push_back(*clock); + } + + //for (Alarm a : alarms) { + // a = *this; + //} + //for (Clock c : clocks) { + // c = this->clock; + //} + return(alarm); @@ -323,13 +359,9 @@ int Alarm::count=0; // !ARGUMENTS: int nameLen, // in const char *name, // in - Clock **clock, // in - Time *ringTime, // in - TimeInterval *ringInterval, // in - Time *stopTime, // in - TimeInterval *ringDuration, // in - int *ringTimeStepCount, // in - Time *refTime, // in + Clock **clock, // in + Time *ringTime, // in + TimeInterval *ringInterval, // in bool *ringing, // in bool *enabled, // in bool *sticky) { // in @@ -398,23 +430,17 @@ int Alarm::count=0; } } if (ringInterval != ESMC_NULL_POINTER) { + TimeInterval zeroTimeInterval(0,0,1,0,0,0); + if(*ringInterval < zeroTimeInterval){ + ESMC_LogDefault.MsgFoundError(ESMC_RC_ARG_BAD, + "; Cannot set negative ringInterval", ESMC_CONTEXT, &rc); + return 0; + } if (this->ringInterval != *ringInterval) { this->ringInterval = *ringInterval; this->userChangedRingInterval = true; } } - if (stopTime != ESMC_NULL_POINTER) { - this->stopTime = *stopTime; - } - if (ringDuration != ESMC_NULL_POINTER) { - this->ringDuration = *ringDuration; - } - if (ringTimeStepCount != ESMC_NULL_POINTER) { - this->ringTimeStepCount = *ringTimeStepCount; - } - if (refTime != ESMC_NULL_POINTER) { - this->refTime = *refTime; - } if (ringing != ESMC_NULL_POINTER) { this->ringing = *ringing; } @@ -425,7 +451,8 @@ int Alarm::count=0; this->sticky = *sticky; if(*sticky) enableSticky(); } - + + // Looks like this implementation is not complete. // TODO: invoke private method, shared with ESMCI_alarmCreate(), to // calculate next ringTime for interval alarms, given ringInterval // and none, one or both of refTime and ringTime. Will replace @@ -467,17 +494,8 @@ void Alarm::enableSticky(void){ char *tempName, // out Clock **clock, // out Time *ringTime, // out - Time *prevRingTime, // out TimeInterval *ringInterval, // out - Time *stopTime, // out - TimeInterval *ringDuration, // out - int *ringTimeStepCount, // out - int *timeStepRingingCount, // out - Time *ringBegin, // out - Time *ringEnd, // out - Time *refTime, // out bool *ringing, // out - bool *ringingOnPrevTimeStep, // out bool *enabled, // out bool *sticky, // out bool *ringerIsOn) { // out @@ -527,39 +545,12 @@ void Alarm::enableSticky(void){ if (ringTime != ESMC_NULL_POINTER) { *ringTime = this->ringTime; } - if (prevRingTime != ESMC_NULL_POINTER) { - *prevRingTime = this->prevRingTime; - } if (ringInterval != ESMC_NULL_POINTER) { *ringInterval = this->ringInterval; } - if (stopTime != ESMC_NULL_POINTER) { - *stopTime = this->stopTime; - } - if (ringDuration != ESMC_NULL_POINTER) { - *ringDuration = this->ringDuration; - } - if (ringTimeStepCount != ESMC_NULL_POINTER) { - *ringTimeStepCount = this->ringTimeStepCount; - } - if (timeStepRingingCount != ESMC_NULL_POINTER) { - *timeStepRingingCount = this->timeStepRingingCount; - } - if (ringBegin != ESMC_NULL_POINTER) { - *ringBegin = this->ringBegin; - } - if (ringEnd != ESMC_NULL_POINTER) { - *ringEnd = this->ringEnd; - } - if (refTime != ESMC_NULL_POINTER) { - *refTime = this->refTime; - } if (ringing != ESMC_NULL_POINTER) { *ringing = this->ringing; } - if (ringingOnPrevTimeStep != ESMC_NULL_POINTER) { - *ringingOnPrevTimeStep = this->ringingOnPrevTimeStep; - } if (enabled != ESMC_NULL_POINTER) { *enabled = this->enabled; } @@ -900,9 +891,7 @@ void Alarm::enableSticky(void){ // get clock's next time if (rc != ESMC_NULL_POINTER) *rc = ESMF_SUCCESS; - Time clockNextTime; - clock->Clock::getNextTime(&clockNextTime, timeStep); - return canRingAtTime(clockNextTime); + return canRingAtNextTime(*clock, timeStep); } // end Alarm::willRingNext @@ -947,8 +936,9 @@ void Alarm::enableSticky(void){ // get clock's prev time if (rc != ESMC_NULL_POINTER) *rc = ESMF_SUCCESS; - Time clockTime = clock->currTime - clock->timeStep; - return canRingAtTime(clockTime); + // Time clockTime = clock->currTime - clock->timeStep; + // return canRingAtTime(clockTime); + return ringingOnPrevTimeStep; } // end Alarm::wasPrevRinging @@ -1087,15 +1077,53 @@ void Alarm::enableSticky(void){ } // end Alarm::isSticky #define DEBUG 1 -bool Alarm::canRingAtTime(const Time & clockTime) const{ +bool Alarm::canRingAtTime(const Clock & clock) { bool retval = false; + // If clock's current time is ahead of alarm->ringTime, adjust alarm->ringTime until + // either ringTime equals clockTime or ringTime is greater than clockTime when + // clock runs forward; Or ringTime is less than clockTime when clock runs reverse. + + // Note ringInterval > 0 is a magnitude + Time clockTime = clock.currTime; + + // One shot alarm that can only ring at ringTime + TimeInterval zeroTimeInterval(0,0,1,0,0,0); + if( this->ringInterval < zeroTimeInterval){ + if(this->ringTime == clockTime ) + return true; + else + return false; + } + + if(clock.direction == ESMF_DIRECTION_FORWARD) { + while (this->ringTime < clockTime){ + this->ringTime = this->ringTime + this->ringInterval; + } + }else if(clock.direction == ESMF_DIRECTION_REVERSE){ + while (this->ringTime > clockTime){ + this->ringTime = this->ringTime - this->ringInterval; + } + } + if(this->ringTime == clockTime) retval = true; return retval; } +bool Alarm::canRingAtNextTime(Clock & clock, TimeInterval * timeStep) const { + bool retval = false; + + Time clockNextTime; + clock.Clock::getNextTime(&clockNextTime, timeStep); + + if(this->ringTime == clockNextTime) + retval = true; + + return retval; +} + //------------------------------------------------------------------------- //BOP // !IROUTINE: Alarm::checkRingTime - check if time to ring @@ -1136,8 +1164,7 @@ bool Alarm::canRingAtTime(const Time & clockTime) const{ ESMC_LogDefault.Write(logMsg, ESMC_LOGMSG_WARN,ESMC_CONTEXT); return(false); } - Time clockTime = clock->currTime; - bool canRing = canRingAtTime( clockTime); // Check if the alarm can ring when time matches. + bool canRing = canRingAtTime(*clock); // Check if the alarm can ring when time matches. if(sticky) { @@ -1146,14 +1173,17 @@ bool Alarm::canRingAtTime(const Time & clockTime) const{ * 2) it didn't ring but now it's the time to ring */ if(ringing || canRing){ // Set ringing true either because it's a sticky ringing alarm or time matches. + ringingOnPrevTimeStep = ringing; ringing = true; if (canRing) updateRingTime(rc); // If the alarm's time match clock time, advance ringTime + if (rc != ESMC_NULL_POINTER) *rc = ESMF_SUCCESS; return (ringing && enabled); } } // Non-sticky one shot alarms, time must match if (canRing){ + ringingOnPrevTimeStep = ringing; ringing = true; updateRingTime(rc); // If the alarm's time match clock time, advance ringTime }else{ @@ -1190,10 +1220,30 @@ bool Alarm::canRingAtTime(const Time & clockTime) const{ if(ringing){ prevRingTime = ringTime; - ringTime = ringTime + ringInterval; + + //if(clock->direction == ESMF_DIRECTION_FORWARD) + // ringTime = ringTime + ringInterval; + //else + // ringTime = ringTime - ringInterval; } } +void Alarm::clockChangeDirection(const ESMC_Direction & old_direction, + const ESMC_Direction & new_direction, + int * rc) { + + #undef ESMC_METHOD + #define ESMC_METHOD "ESMCI::Alarm::clockChangeDirection()" + + // If the direction didn't change, do nothing + if(old_direction == new_direction ) return; + + if(old_direction == ESMF_DIRECTION_FORWARD) + ringTime = ringTime - ringInterval; // ringTime goes backward by 1 interval + else + ringTime = ringTime + ringInterval; // ringTime goes forward by 1 interval +} + //------------------------------------------------------------------------- //BOP // !IROUTINE: Alarm(==) - Alarm equality comparison @@ -1493,14 +1543,6 @@ bool Alarm::canRingAtTime(const Time & clockTime) const{ prevRingTime.Time::print(); } } - else if (strncmp(opts, "stoptime", 8) == 0) { - printf("stopTime = \n"); - if (strstr(opts, "string") != ESMC_NULL_POINTER) { - stopTime.Time::print("string"); - } else { - stopTime.Time::print(); - } - } else if (strncmp(opts, "ringbegin", 9) == 0) { printf("ringBegin = \n"); if (strstr(opts, "string") != ESMC_NULL_POINTER) { @@ -1517,17 +1559,6 @@ bool Alarm::canRingAtTime(const Time & clockTime) const{ ringEnd.Time::print(); } } - else if (strncmp(opts, "reftime", 7) == 0) { - printf("refTime = \n"); - if (strstr(opts, "string") != ESMC_NULL_POINTER) { - refTime.Time::print("string"); - } else { - refTime.Time::print(); - } - } - else if (strncmp(opts, "timestepringingcount", 20) == 0) { - printf("timeStepRingingCount = %d\n", timeStepRingingCount); - } else if (strncmp(opts, "ringingonprevtimestep", 21) == 0) { printf("ringingOnPrevTimeStep = %s\n", ringingOnPrevTimeStep ? "true" : "false"); @@ -1549,14 +1580,11 @@ bool Alarm::canRingAtTime(const Time & clockTime) const{ printf("name = %s\n", name); printf("ringInterval = \n"); ringInterval.TimeInterval::print(options); - printf("ringDuration = \n"); ringDuration.TimeInterval::print(options); printf("ringTime = \n"); ringTime.Time::print(options); printf("firstRingTime = \n"); firstRingTime.Time::print(options); printf("prevRingTime = \n"); prevRingTime.Time::print(options); - printf("stopTime = \n"); stopTime.Time::print(options); printf("ringBegin = \n"); ringBegin.Time::print(options); printf("ringEnd = \n"); ringEnd.Time::print(options); - printf("refTime = \n"); refTime.Time::print(options); printf("ringTimeStepCount = %d\n", ringTimeStepCount); printf("timeStepRingingCount = %d\n", timeStepRingingCount); printf("ringing = %s\n", ringing ? "true" : "false"); diff --git a/src/Infrastructure/TimeMgr/src/ESMCI_Clock.C b/src/Infrastructure/TimeMgr/src/ESMCI_Clock.C index 720e37c001..50cb63f032 100644 --- a/src/Infrastructure/TimeMgr/src/ESMCI_Clock.C +++ b/src/Infrastructure/TimeMgr/src/ESMCI_Clock.C @@ -365,6 +365,12 @@ int Clock::count=0; if (advanceCount != ESMC_NULL_POINTER) this->advanceCount = *advanceCount; if (direction != ESMC_NULL_POINTER) { + // traverse alarm list (i) to update ringTime + for(int i=0; iAlarm::clockChangeDirection(this->direction, *direction, &rc); + } + this->direction = *direction; this->userChangedDirection = true; } diff --git a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 index 76a343c7c4..4f0bae1d39 100644 --- a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 +++ b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 @@ -114,6 +114,9 @@ program ESMF_AlarmTest esmf_360dayCalendar = ESMF_CalendarCreate(ESMF_CALKIND_360DAY, & name="360Day", rc=rc) + call ESMF_CalendarSetDefault ( ESMF_CALKIND_GREGORIAN, rc=rc ) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize() + !------------------------------------------------------------------------------- ! The unit tests are divided into Sanity and Exhaustive. The Sanity tests are ! always run. When the environment variable, EXHAUSTIVE, is set to ON then @@ -507,26 +510,6 @@ program ESMF_AlarmTest ! ---------------------------------------------------------------------------- - !EX_UTest - !Test if destroyed Alarm Previously ringing - write(failMsg, *) " Did not return ESMF_RC_OBJ_DELETED" - write(name, *) "Destroyed Alarm Was Previously ringing Test" - bool = ESMF_AlarmWasPrevRinging(alarm1, rc=rc) - call ESMF_Test((rc.eq.ESMF_RC_OBJ_DELETED), & - name, failMsg, result, ESMF_SRCLINE) - - ! ---------------------------------------------------------------------------- - - !EX_UTest - !Test if non-created Alarm Previously ringing - write(failMsg, *) " Did not return ESMF_RC_OBJ_NOT_CREATED" - write(name, *) "Non-created Alarm Was Previously ringing Test" - bool = ESMF_AlarmWasPrevRinging(alarm6, rc=rc) - call ESMF_Test((rc.eq.ESMF_RC_OBJ_NOT_CREATED), & - name, failMsg, result, ESMF_SRCLINE) - - ! ---------------------------------------------------------------------------- - !EX_UTest write(failMsg, *) " Did not return ESMF_RC_OBJ_DELETED" write(name, *) "Turn off Ringing on destroyed Alarm " @@ -543,25 +526,6 @@ program ESMF_AlarmTest call ESMF_Test((rc.eq.ESMF_RC_OBJ_NOT_CREATED), & name, failMsg, result, ESMF_SRCLINE) - ! ---------------------------------------------------------------------------- - - !EX_UTest - !Test destroyed Alarm will ring next - write(failMsg, *) " Did not return ESMF_RC_OBJ_DELETED" - write(name, *) "Destroyed Alarm will ring next Test" - willRingNext = ESMF_AlarmWillRingNext(alarm1, timeStep=timeStep, rc=rc) - call ESMF_Test((rc.eq.ESMF_RC_OBJ_DELETED), & - name, failMsg, result, ESMF_SRCLINE) - - ! ---------------------------------------------------------------------------- - - !EX_UTest - !Test non-created Alarm will ring next - write(failMsg, *) " Did not return ESMF_RC_OBJ_NOT_CREATED" - write(name, *) "Non-created Alarm will ring next Test" - willRingNext = ESMF_AlarmWillRingNext(alarm6, timeStep=timeStep, rc=rc) - call ESMF_Test((rc.eq.ESMF_RC_OBJ_NOT_CREATED), & - name, failMsg, result, ESMF_SRCLINE) ! ---------------------------------------------------------------------------- @@ -1077,2406 +1041,274 @@ program ESMF_AlarmTest call ESMF_Test((rc.eq.ESMF_SUCCESS), & name, failMsg, result, ESMF_SRCLINE) - ! ---------------------------------------------------------------------------- + call ESMF_AlarmDestroy (alarm, rc=rc) + call ESMF_ClockDestroy (clock, rc=rc) - !EX_UTest - !Test Alarm will ring next - call ESMF_ClockAdvance(clock, rc=rc) - call ESMF_ClockAdvance(clock, rc=rc) - write(failMsg, *) " Did not return ESMF_SUCCESS or returned wrong state" - write(name, *) "Alarm will ring next Test" - willRingNext = ESMF_AlarmWillRingNext(alarm, timeStep=timeStep, rc=rc) - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(.not.willRingNext), & - name, failMsg, result, ESMF_SRCLINE) - ! ---------------------------------------------------------------------------- !EX_UTest - !Test Get Clock Next Time - write(failMsg, *) " Did not return ESMF_SUCCESS)" - write(name, *) "Get Clock Next Time Test" - call ESMF_ClockGetNextTime(clock, nextTime, timeStep=timeStep, rc=rc) + write(failMsg, *) " Did not return ESMF_SUCCESS" + write(name, *) "Forward Alarm Test Case 1" + call ForwardAlarm_Test1(rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), & name, failMsg, result, ESMF_SRCLINE) - - ! ---------------------------------------------------------------------------- - !EX_UTest - !Test Alarm will ring next - call ESMF_ClockAdvance(clock, rc=rc) - write(failMsg, *) " Did not return ESMF_SUCCESS or returned wrong state" - write(name, *) "Alarm will ring next Test" - willRingNext = ESMF_AlarmWillRingNext(alarm, timeStep=timeStep, rc=rc) - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(willRingNext), & - name, failMsg, result, ESMF_SRCLINE) - ! ---------------------------------------------------------------------------- !EX_UTest - !Test Get Time from clock write(failMsg, *) " Did not return ESMF_SUCCESS" - write(name, *) "Get Clock Current Time Test" - call ESMF_ClockGet(clock, currTime=currentTime, rc=rc) + write(name, *) "Forward Alarm Test Case 2" + call ForwardAlarm_Test2(rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), & name, failMsg, result, ESMF_SRCLINE) - - ! ---------------------------------------------------------------------------- - !EX_UTest - !Test that Clock Get Next Time Passed - !Testing ESMF_TimeOperator(==)(time1,time2) - write(failMsg, *) " Next Time not equal to current Time" - write(name, *) "Get Clock Next Time Test" - bool = (nextTime == currentTime) ! exercising Time == operator - call ESMF_Test((bool), & - name, failMsg, result, ESMF_SRCLINE) - ! ---------------------------------------------------------------------------- !EX_UTest - !Test Alarm ringing - call ESMF_ClockAdvance(clock, rc=rc) - write(failMsg, *) " Did not return ESMF_SUCCESS or returned wrong state" - write(name, *) "Alarm is ringing Test" - bool = ESMF_AlarmIsRinging(alarm, rc=rc) - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(bool), & + write(failMsg, *) " Did not return ESMF_SUCCESS" + write(name, *) "Forward Alarm Test Case 3" + call ForwardAlarm_Test3(rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), & name, failMsg, result, ESMF_SRCLINE) - - ! ---------------------------------------------------------------------------- - !EX_UTest - !Test Alarm still ringing - call ESMF_ClockAdvance(clock, rc=rc) - write(failMsg, *) " Did not return ESMF_SUCCESS or returned wrong state" - write(name, *) "Alarm is still ringing Test" - bool = ESMF_AlarmIsRinging(alarm, rc=rc) - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(bool), & - name, failMsg, result, ESMF_SRCLINE) - ! ---------------------------------------------------------------------------- !EX_UTest - !Test Alarm Previously ringing - write(failMsg, *) " Did not return ESMF_SUCCESS or returned wrong state" - write(name, *) "Alarm Was Previously ringing Test" - bool = ESMF_AlarmWasPrevRinging(alarm, rc=rc) - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(bool), & + write(failMsg, *) " Did not return ESMF_SUCCESS" + write(name, *) "Forward Alarm Test Case 4" + call ForwardAlarm_Test4(rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), & name, failMsg, result, ESMF_SRCLINE) - !print *, "bool is ", bool - ! ---------------------------------------------------------------------------- !EX_UTest - !Test Alarm Previously ringing - call ESMF_ClockAdvance(clock, rc=rc) - write(failMsg, *) " Did not return ESMF_SUCCESS or returned wrong state" - write(name, *) "Alarm Was Previously ringing Test" - bool = ESMF_AlarmWasPrevRinging(alarm, rc=rc) - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(bool), & + write(failMsg, *) " Did not return ESMF_SUCCESS" + write(name, *) "Forward Alarm Test Case 5" + call ForwardAlarm_Test5(rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), & name, failMsg, result, ESMF_SRCLINE) ! ---------------------------------------------------------------------------- !EX_UTest - !Test Alarm still ringing - call ESMF_ClockAdvance(clock, rc=rc) - call ESMF_ClockAdvance(clock, rc=rc) - call ESMF_ClockAdvance(clock, rc=rc) - call ESMF_ClockAdvance(clock, rc=rc) - call ESMF_ClockAdvance(clock, rc=rc) - call ESMF_ClockAdvance(clock, rc=rc) - call ESMF_ClockAdvance(clock, rc=rc) - call ESMF_ClockAdvance(clock, rc=rc) - write(failMsg, *) " Did not return ESMF_SUCCESS or returned wrong state" - write(name, *) "Alarm is still ringing Test" - bool = ESMF_AlarmIsRinging(alarm, rc=rc) - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(bool), & + write(failMsg, *) " Did not return ESMF_SUCCESS" + write(name, *) "Forward Alarm Test Case 6" + call ForwardAlarm_Test6(rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), & name, failMsg, result, ESMF_SRCLINE) ! ---------------------------------------------------------------------------- !EX_UTest write(failMsg, *) " Did not return ESMF_SUCCESS" - write(name, *) "Turn off Ringing Alarm " - call ESMF_AlarmRingerOff(alarm, rc=rc) + write(name, *) "Reverse Alarm Test Case 1" + call ReverseAlarm_Test1(rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), & name, failMsg, result, ESMF_SRCLINE) ! ---------------------------------------------------------------------------- !EX_UTest - write(failMsg, *) " Did not return ESMF_SUCCESS or its ringing" - write(name, *) "Check if Alarm is not ringing Test" - isringing = ESMF_AlarmIsRinging(alarm, rc=rc) - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(.not.isringing), & + write(failMsg, *) " Did not return ESMF_SUCCESS" + write(name, *) "Reverse Alarm Test Case 2" + call ReverseAlarm_Test2(rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), & name, failMsg, result, ESMF_SRCLINE) ! ---------------------------------------------------------------------------- !EX_UTest - !Test Alarm Previously ringing - write(failMsg, *) " Did not return ESMF_SUCCESS or returned wrong state" - write(name, *) "Alarm Was Previously ringing Test" - bool = ESMF_AlarmWasPrevRinging(alarm, rc=rc) - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(bool), & + write(failMsg, *) " Did not return ESMF_SUCCESS" + write(name, *) "Reverse Alarm Test Case 3" + call ReverseAlarm_Test3(rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), & name, failMsg, result, ESMF_SRCLINE) ! ---------------------------------------------------------------------------- !EX_UTest - !Test Alarm Previously ringing - call ESMF_ClockAdvance(clock, rc=rc) - write(failMsg, *) " Did not return ESMF_SUCCESS or returned wrong state" - write(name, *) "Alarm Was Previously ringing Test" - bool = ESMF_AlarmWasPrevRinging(alarm, rc=rc) - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(bool), & + write(failMsg, *) " Did not return ESMF_SUCCESS" + write(name, *) "Reverse Alarm Test Case 4" + call ReverseAlarm_Test4(rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), & name, failMsg, result, ESMF_SRCLINE) ! ---------------------------------------------------------------------------- !EX_UTest - !Test Alarm Previously ringing - call ESMF_ClockAdvance(clock, rc=rc) - write(failMsg, *) " Did not return ESMF_SUCCESS or returned wrong state" - write(name, *) "Alarm Was Previously ringing Test" - bool = ESMF_AlarmWasPrevRinging(alarm, rc=rc) - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(bool), & + write(failMsg, *) " Did not return ESMF_SUCCESS" + write(name, *) "Reverse Alarm Test Case 5" + call ReverseAlarm_Test5(rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), & name, failMsg, result, ESMF_SRCLINE) - call ESMF_AlarmDestroy (alarm, rc=rc) - call ESMF_ClockDestroy (clock, rc=rc) - - ! ---------------------------------------------------------------------------- - - ! Initialize clock - !EX_UTest - write(name, *) "Clock Initialization Test" - write(failMsg, *) " Did not return ESMF_SUCCESS" - clock = ESMF_ClockCreate(timeStep, startTime, stopTime=stopTime, & - name="Clock 1", rc=rc) - call ESMF_Test((rc.eq.ESMF_SUCCESS), & - name, failMsg, result, ESMF_SRCLINE) ! ---------------------------------------------------------------------------- !EX_UTest write(failMsg, *) " Did not return ESMF_SUCCESS" - write(name, *) "Non-Sticky Alarm Time Initialization Test" - alarm = ESMF_AlarmCreate(name="alarm1", clock=clock, & - ringTime=alarmTime, sticky=.FALSE., rc=rc) + write(name, *) "Reverse Alarm Test Case 6" + call ReverseAlarm_Test6(rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), & name, failMsg, result, ESMF_SRCLINE) - ! ---------------------------------------------------------------------------- - !EX_UTest - !Test Alarm will ring next - call ESMF_ClockAdvance(clock, rc=rc) - call ESMF_ClockAdvance(clock, rc=rc) - write(failMsg, *) " Did not return ESMF_SUCCESS or returned wrong state" - write(name, *) "Alarm will ring next Test" - willRingNext = ESMF_AlarmWillRingNext(alarm, timeStep=timeStep, rc=rc) - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(.not.willRingNext), & - name, failMsg, result, ESMF_SRCLINE) - ! ---------------------------------------------------------------------------- !EX_UTest - !Test Alarm will ring next - call ESMF_ClockAdvance(clock, rc=rc) - write(failMsg, *) " Did not return ESMF_SUCCESS or returned wrong state" - write(name, *) "Alarm will ring next Test" - willRingNext = ESMF_AlarmWillRingNext(alarm, timeStep=timeStep, rc=rc) - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(willRingNext), & + write(failMsg, *) " Did not return ESMF_SUCCESS" + write(name, *) "Forward then Reverse Alarm Test Case 1" + call ForwardReverseAlarm_Test1(rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), & name, failMsg, result, ESMF_SRCLINE) - - ! ---------------------------------------------------------------------------- - !EX_UTest - !Test Alarm ringing - call ESMF_ClockAdvance(clock, rc=rc) - write(failMsg, *) " Did not return ESMF_SUCCESS or returned wrong state" - write(name, *) "Alarm is ringing Test" - bool = ESMF_AlarmIsRinging(alarm, rc=rc) - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(bool), & - name, failMsg, result, ESMF_SRCLINE) - ! ---------------------------------------------------------------------------- !EX_UTest - !Test Alarm still ringing - call ESMF_ClockAdvance(clock, rc=rc) - write(failMsg, *) " Did not return ESMF_SUCCESS or returned wrong state" - write(name, *) "Alarm is still ringing Test" - bool = ESMF_AlarmIsRinging(alarm, rc=rc) - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(bool), & + write(failMsg, *) " Did not return ESMF_SUCCESS" + write(name, *) "Forward then Reverse Alarm Test Case 2" + call ForwardReverseAlarm_Test2(rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), & name, failMsg, result, ESMF_SRCLINE) - + ! ---------------------------------------------------------------------------- !EX_UTest - !Test Alarm Previously ringing - write(failMsg, *) " Did not return ESMF_SUCCESS or returned wrong state" - write(name, *) "Alarm Was Previously ringing Test" - bool = ESMF_AlarmWasPrevRinging(alarm, rc=rc) - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(bool), & + write(failMsg, *) " Did not return ESMF_SUCCESS" + write(name, *) "Forward then Reverse Alarm Test Case 3" + call ForwardReverseAlarm_Test3(rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), & name, failMsg, result, ESMF_SRCLINE) - !print *, "bool is ", bool - ! ---------------------------------------------------------------------------- - !EX_UTest - !Test Alarm Previously ringing - call ESMF_ClockAdvance(clock, rc=rc) - write(failMsg, *) " Did not return ESMF_SUCCESS or returned wrong state" - write(name, *) "Alarm Was Previously ringing Test" - bool = ESMF_AlarmWasPrevRinging(alarm, rc=rc) - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(bool), & - name, failMsg, result, ESMF_SRCLINE) + write(failMsg, *) " Alarms with ClockSet... " + write(name, *) "Test ClockSet after alarm attached to clock " + rc = ESMF_SUCCESS + testPass = .true. + call Test_ClockSet(testPass, rc) + if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. + if (.not. testPass) print *, 'bad return codes discovered' + call ESMF_Test (testPass, name, failMsg, result, ESMF_SRCLINE) ! ---------------------------------------------------------------------------- - !EX_UTest - !Test destroying alarm - write(failMsg, *) " Did not return ESMF_SUCCESS" - write(name, *) "Destroying alarm test" - call ESMF_AlarmDestroy (alarm, rc=rc) - call ESMF_Test(rc == ESMF_SUCCESS, name, failMsg, result, ESMF_SRCLINE) + ! The following tests are from Ben@NASA's support ticket 3614994 + write(failMsg, *) " Alarms did not rewind correct number of times " + write(name, *) "Test multiple alarms rewind correct number of times " + rc = ESMF_SUCCESS + testPass = .true. + call Test_ReverseAlarms(testPass, rc) + if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. + if (.not. testPass) print *, 'bad return codes discovered' + call ESMF_Test (testPass, name, failMsg, result, ESMF_SRCLINE) ! ---------------------------------------------------------------------------- - !EX_UTest - !Test destroying clock after alarm - write(failMsg, *) " Did not return ESMF_SUCCESS" - write(name, *) "Destroying clock after alarm test" - call ESMF_ClockDestroy (clock, rc=rc) - call ESMF_Test(rc == ESMF_SUCCESS, name, failMsg, result, ESMF_SRCLINE) + write(failMsg, *) " Alarms hang... " + write(name, *) "Test multiple alarms replay without hanging " + rc = ESMF_SUCCESS + testPass = .true. + call Test_AlarmHang(testPass, rc) + if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. + if (.not. testPass) print *, 'bad return codes discovered' + call ESMF_Test (testPass, name, failMsg, result, ESMF_SRCLINE) ! ---------------------------------------------------------------------------- - !EX_UTest - !Test Non-Sticky Alarms 1 - ! from Chris Hill via support issue 988241, bug 996229 - write(failMsg, *) " Did not return nstep=48, sstep=73, i=144, and ESMF_SUCCESS" - write(name, *) "Non-Sticky Alarm Test 1" - call ESMF_TimeIntervalSet(timeStep, s=100, rc=rc) - call ESMF_TimeIntervalSet(alarmStep, s=150, rc=rc) - call ESMF_TimeSet(startTime, yy=1999, mm=12, dd=31, h=23, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeSet(stopTime, yy=2000, mm=1, dd=1, h=3, & - calendar=gregorianCalendar, rc=rc) - clock2=ESMF_ClockCreate(timeStep, startTime, stopTime=stopTime, & - name="Clock 2", rc=rc) - call ESMF_TimeSet(alarmTime, yy=2000, mm=1, dd=1, h=1, & - calendar=gregorianCalendar, rc=rc) - alarm4 = ESMF_AlarmCreate(clock=clock2, ringTime=alarmTime, & - ringInterval=alarmStep, sticky=.false., rc=rc) - ! number of clock time steps alarm rings for - nstep = 0 - - ! starting time step number for first alarm ring - sstep = 0 - - ! total clock time steps - i = 0 - - ! run the clock - do while (.not. ESMF_ClockIsStopTime(clock2, rc=rc)) - i = i + 1 - call ESMF_ClockGetAlarmList(clock2, ESMF_ALARMLIST_RINGING, & - alarmList=alarmList, & - alarmCount=alarmCount, rc=rc) - if (alarmCount .gt. 0) then - if (sstep .eq. 0) sstep = i - nstep = nstep + 1 - endif - call ESMF_ClockAdvance(clock2, rc=rc) - enddo - - call ESMF_Test((rc.eq.ESMF_SUCCESS) & - .and.(nstep.eq.48).and.(sstep.eq.73).and.(i.eq.144), & - name, failMsg, result, ESMF_SRCLINE) - - call ESMF_AlarmDestroy(alarm4, rc=rc) - call ESMF_ClockDestroy(clock2, rc=rc) + write(failMsg, *) " Alarms with ring intervals equal to clock interval, incorrect behavior " + write(name, *) "Test running an alarms forward-reverse-forward with ring interval equal to clock interval " + rc = ESMF_SUCCESS + testPass = .true. + call Test_AlarmAdvRewind(testPass, rc) + if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. + if (.not. testPass) print *, 'bad return codes discovered' + call ESMF_Test (testPass, name, failMsg, result, ESMF_SRCLINE) ! ---------------------------------------------------------------------------- - !EX_UTest - !Test Non-Sticky Alarms 2 - ! Test ringDuration and stopTime - write(failMsg, *) " Did not return nstep=12 and ESMF_SUCCESS" - write(name, *) "Non-Sticky Alarm Test 2" - call ESMF_TimeIntervalSet(timeStep, m=15, rc=rc) - call ESMF_TimeSet(startTime, yy=1999, mm=12, dd=31, h=23, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeSet(stopTime, yy=2000, mm=1, dd=1, h=23, & - calendar=gregorianCalendar, rc=rc) - clock2 = ESMF_ClockCreate(timeStep, startTime, stopTime=stopTime, & - name="Clock 2", rc=rc) - call ESMF_TimeSet(alarmTime, yy=2000, mm=1, dd=1, h=1, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeIntervalSet(alarmStep, h=2, rc=rc) - call ESMF_TimeIntervalSet(ringDuration, m=30, rc=rc) - call ESMF_TimeSet(alarmStopTime, yy=2000, mm=1, dd=1, h=13, & - calendar=gregorianCalendar, rc=rc) - alarm4 = ESMF_AlarmCreate(clock=clock2, ringTime=alarmTime, & - ringInterval=alarmStep, & - ringDuration=ringDuration, & - stopTime=alarmStopTime, sticky=.false., rc=rc) - ! number of clock time steps alarm rings for - nstep = 0 - - ! run the clock - do while (.not. ESMF_ClockIsStopTime(clock2, rc=rc)) - if (ESMF_AlarmIsRinging(alarm4)) then - nstep = nstep + 1 - endif - call ESMF_ClockAdvance(clock2, rc=rc) - enddo - - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(nstep.eq.12), & - name, failMsg, result, ESMF_SRCLINE) - call ESMF_AlarmDestroy(alarm4, rc=rc) - call ESMF_ClockDestroy(clock2, rc=rc) + write(failMsg, *) " Alarms reverse with sticky set... " + write(name, *) "Test running an alarm reverse with sticky bit set " + rc = ESMF_SUCCESS + testPass = .true. + call Test_RevAlarmSticky(60._ESMF_KIND_R8, testPass, rc) + if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. + if (.not. testPass) print *, 'bad return codes discovered' + call ESMF_Test (testPass, name, failMsg, result, ESMF_SRCLINE) ! ---------------------------------------------------------------------------- - !EX_UTest - !Test Non-Sticky Alarms 3 - ! Test ringTimeStepCount and stopTime - write(failMsg, *) " Did not return nstep=18 and ESMF_SUCCESS" - write(name, *) "Non-Sticky Alarm Test 3" - call ESMF_TimeIntervalSet(timeStep, m=15, rc=rc) - call ESMF_TimeSet(startTime, yy=1999, mm=12, dd=31, h=23, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeSet(stopTime, yy=2000, mm=1, dd=1, h=23, & - calendar=gregorianCalendar, rc=rc) - clock2=ESMF_ClockCreate(timeStep, startTime, stopTime=stopTime, & - name="Clock 2", rc=rc) - call ESMF_TimeSet(alarmTime, yy=2000, mm=1, dd=1, h=1, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeIntervalSet(alarmStep, h=2, rc=rc) - call ESMF_TimeSet(alarmStopTime, yy=2000, mm=1, dd=1, h=13, & - calendar=gregorianCalendar, rc=rc) - alarm4 = ESMF_AlarmCreate(clock=clock2, ringTime=alarmTime, & - ringInterval=alarmStep, & - ringTimeStepCount=3, & - stopTime=alarmStopTime, sticky=.false., rc=rc) - ! number of clock time steps alarm rings for - nstep = 0 - - ! run the clock - do while (.not. ESMF_ClockIsStopTime(clock2, rc=rc)) - if (ESMF_AlarmIsRinging(alarm4)) then - nstep = nstep + 1 - endif - call ESMF_ClockAdvance(clock2, rc=rc) - enddo - - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(nstep.eq.18), & - name, failMsg, result, ESMF_SRCLINE) - - call ESMF_AlarmDestroy(alarm4, rc=rc) - call ESMF_ClockDestroy(clock2, rc=rc) +#if 1 + write(failMsg, *) " Alarms with getPrevRingTime... " + write(name, *) "Test getPrevRingTime... after alarm attached to clock " + rc = ESMF_SUCCESS + testPass = .true. + call Test_GetPrevRingTime(testPass, rc) + if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. + if (.not. testPass) print *, 'bad return codes discovered' + call ESMF_Test (testPass, name, failMsg, result, ESMF_SRCLINE) +#endif ! ---------------------------------------------------------------------------- + ! ---------------------------------------------------------------------------- +#endif - !EX_UTest - !Test Non-Sticky Alarms 4 - ! Test ringTimeStepCount precedence over ringDuration - write(failMsg, *) " Did not return nstep=18 and ESMF_SUCCESS" - write(name, *) "Non-Sticky Alarm Test 4" - call ESMF_TimeIntervalSet(timeStep, m=15, rc=rc) - call ESMF_TimeSet(startTime, yy=1999, mm=12, dd=31, h=23, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeSet(stopTime, yy=2000, mm=1, dd=1, h=23, & - calendar=gregorianCalendar, rc=rc) - clock2=ESMF_ClockCreate(timeStep, startTime, stopTime=stopTime, & - name="Clock 2", rc=rc) - call ESMF_TimeSet(alarmTime, yy=2000, mm=1, dd=1, h=1, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeIntervalSet(alarmStep, h=2, rc=rc) - - call ESMF_TimeIntervalSet(ringDuration, m=30, rc=rc) + ! destroy calendars + call ESMF_CalendarDestroy(esmf_360dayCalendar, rc=rc) + call ESMF_CalendarDestroy(no_leapCalendar, rc=rc) + call ESMF_CalendarDestroy(julianCalendar, rc=rc) + call ESMF_CalendarDestroy(gregorianCalendar, rc=rc) - call ESMF_TimeSet(alarmStopTime, yy=2000, mm=1, dd=1, h=13, & - calendar=gregorianCalendar, rc=rc) - alarm4 = ESMF_AlarmCreate(clock=clock2, ringTime=alarmTime, & - ringInterval=alarmStep, & - ringTimeStepCount=3, & - ringDuration=ringDuration, & - stopTime=alarmStopTime, sticky=.false., rc=rc) - ! number of clock time steps alarm rings for - nstep = 0 - - ! run the clock - do while (.not. ESMF_ClockIsStopTime(clock2, rc=rc)) - if (ESMF_AlarmIsRinging(alarm4)) then - nstep = nstep + 1 - endif - call ESMF_ClockAdvance(clock2, rc=rc) - enddo + ! finalize ESMF framework + call ESMF_TestEnd(ESMF_SRCLINE) - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(nstep.eq.18), & - name, failMsg, result, ESMF_SRCLINE) +#if 1 + contains - call ESMF_AlarmDestroy(alarm4, rc=rc) - call ESMF_ClockDestroy(clock2, rc=rc) + subroutine test_reverseAlarms(testPass, rc) + implicit none - ! ---------------------------------------------------------------------------- + logical, intent(out) :: testPass + integer :: status,rc - !EX_UTest - !Test Non-Sticky Alarms 5 - ! Test reverse non-sticky alarm - write(failMsg, *) "Did not return nstep=24, forwardCount=96, reverseCount=0, etc., and ESMF_SUCCESS" - write(name, *) "Non-Sticky Alarm Test 5" - call ESMF_TimeIntervalSet(timeStep, m=15, rc=rc) - call ESMF_TimeSet(startTime, yy=1999, mm=12, dd=31, h=23, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeSet(stopTime, yy=2000, mm=1, dd=1, h=23, & - calendar=gregorianCalendar, rc=rc) - clock2 = ESMF_ClockCreate(timeStep, startTime, stopTime=stopTime, & - name="Clock 2", rc=rc) - call ESMF_TimeSet(alarmTime, yy=2000, mm=1, dd=1, h=1, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeIntervalSet(alarmStep, h=2, rc=rc) - call ESMF_TimeIntervalSet(ringDuration, m=30, rc=rc) - call ESMF_TimeSet(alarmStopTime, yy=2000, mm=1, dd=1, h=13, & - calendar=gregorianCalendar, rc=rc) - alarm4 = ESMF_AlarmCreate(clock=clock2, ringTime=alarmTime, & - ringInterval=alarmStep, & - ringDuration=ringDuration, & - stopTime=alarmStopTime, sticky=.false., rc=rc) - ! number of clock time steps alarm rings for - nstep = 0 - - ! number of times the clock has been run - nclock = 0 - - do while (nclock < 2) - ! run the clock - do while (.not. ESMF_ClockIsDone(clock2, rc=rc)) - !call ESMF_ClockGet(clock2, currTime=currentTime, rc=rc) - !call ESMF_TimeGet(currentTime, yy=yy, mm=mm, dd=dd, h=h, m=m, rc=rc) - !print *, mm, "/", dd, "/", yy, " ", h, ":", m - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - if (ESMF_AlarmIsRinging(alarm4)) then - nstep = nstep + 1 - !print *, "on" - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - else - !print *, "off" - endif - !call ESMF_AlarmPrint(alarm4, options="ringtime string", rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - call ESMF_ClockAdvance(clock2, rc=rc) - enddo - - if (nclock.eq.0) then - call ESMF_ClockGet(clock2, direction=forwardDirection, & - advanceCount=forwardCount, rc=rc) - !print *, "forwardCount = ", forwardCount - else - call ESMF_ClockGet(clock2, direction=reverseDirection, & - advanceCount=reverseCount, rc=rc) - !print *, "reverseCount = ", reverseCount - endif - - call ESMF_ClockSet(clock2, direction=ESMF_DIRECTION_REVERSE, rc=rc) - nclock = nclock + 1 + type(ESMF_TimeInterval) :: dt + type(ESMF_Time) :: start_time, clock_start, clock_end + type(ESMF_Clock) :: clock + character(len=5) :: add_2nd + integer :: nargs - enddo + type(ESMF_TimeInterval) :: tint + type(ESMF_Alarm) :: esmfalarm, firstalarm - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(nstep.eq.24).and. & - (forwardCount.eq.96).and.(reverseCount.eq.0).and. & - (forwardDirection.eq.ESMF_DIRECTION_FORWARD).and. & - (reverseDirection.eq.ESMF_DIRECTION_REVERSE).and. & - ESMF_ClockIsReverse(clock2), & - name, failMsg, result, ESMF_SRCLINE) + integer :: i,nstep, nrings1, nrings2 - !print *, "nstep = ", nstep, " nclock = ", nclock - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) + type(ESMF_Time) :: time + character(len=10) :: iam='test_clock' + logical :: esmf_ring + integer :: nalarms, n_rings=0 - call ESMF_AlarmDestroy(alarm4, rc=rc) - call ESMF_ClockDestroy(clock2, rc=rc) + testPass = .false. + call ESMF_CalendarSetDefault ( ESMF_CALKIND_GREGORIAN, rc=status ) + call verify_(status) + call ESMF_TimeSet(clock_start,yy=2000,mm=1,dd=1,h=21,m=0,s=0,rc=status) + call verify_(status) + call ESMF_TimeSet(clock_end,yy=2000,mm=12,dd=1,h=21,m=0,s=0,rc=status) + call verify_(status) + call ESMF_TimeSet(start_time,yy=2000,mm=10,dd=1,h=21,m=0,s=0,rc=status) + call verify_(status) + call ESMF_TimeIntervalSet(dt,S=900, sN=0, sD=1,rc=status) + call verify_(status) + clock= ESMF_ClockCreate(timeStep=dt,startTime=clock_start,stopTime=clock_end,rc=status) + call verify_(status) + call ESMF_ClockSet(clock,currTime=start_time,rc=status) + call verify_(status) - ! ---------------------------------------------------------------------------- - - !EX_UTest - !Test Non-Sticky Alarms 6 - ! Test reverse non-sticky alarm with negative timestep - write(failMsg, *) "Did not return nring=48, forwardCount=96, reverseCount=0, etc., and ESMF_SUCCESS" - write(name, *) "Non-Sticky Alarm Test 6" - call ESMF_TimeIntervalSet(timeStep, m=-15, rc=rc) - call ESMF_TimeSet(startTime, yy=2000, mm=1, dd=1, h=23, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeSet(stopTime, yy=1999, mm=12, dd=31, h=23, & - calendar=gregorianCalendar, rc=rc) - clock2 = ESMF_ClockCreate(timeStep, startTime, stopTime=stopTime, & - name="Clock 2", rc=rc) - call ESMF_TimeSet(alarmTime, yy=2000, mm=1, dd=1, h=23, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeIntervalSet(alarmStep, h=-2, rc=rc) - call ESMF_TimeIntervalSet(ringDuration, m=-30, rc=rc) - call ESMF_TimeSet(alarmStopTime, yy=1999, mm=12, dd=31, h=21, & - calendar=gregorianCalendar, rc=rc) - alarm4 = ESMF_AlarmCreate(clock=clock2, ringTime=alarmTime, & - ringInterval=alarmStep, & - ringDuration=ringDuration, & - stopTime=alarmStopTime, & - sticky=.false., rc=rc) - ! number of clock time steps alarm rings for - nring = 0 - - ! number of times the clock has been run - nclock = 0 - - do while (nclock < 2) - ! run the clock - do while (.not. ESMF_ClockIsDone(clock2, rc=rc)) - call ESMF_ClockGet(clock2, currTime=currentTime, rc=rc) - call ESMF_TimeGet(currentTime, yy=yy, mm=mm, dd=dd, h=h, m=m, rc=rc) - !print *, mm, "/", dd, "/", yy, " ", h, ":", m - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - if (ESMF_AlarmIsRinging(alarm4)) then - nring = nring + 1 - !print *, "ringing!" - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - endif - !call ESMF_AlarmPrint(alarm4, options="ringbegin string", rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - !call ESMF_AlarmPrint(alarm4, options="ringtime string", rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - call ESMF_ClockAdvance(clock2, rc=rc) - enddo - - if (nclock.eq.0) then - call ESMF_ClockGet(clock2, direction=forwardDirection, & - advanceCount=forwardCount, rc=rc) - !print *, "forwardCount = ", forwardCount - else - call ESMF_ClockGet(clock2, direction=reverseDirection, & - advanceCount=reverseCount, rc=rc) - !print *, "reverseCount = ", reverseCount - endif - - !print *, "Going in REVERSE ..." - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - call ESMF_ClockSet(clock2, direction=ESMF_DIRECTION_REVERSE, rc=rc) - nclock = nclock + 1 - - enddo - - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(nring.eq.48).and. & - (forwardCount.eq.96).and.(reverseCount.eq.0).and. & - (forwardDirection.eq.ESMF_DIRECTION_FORWARD).and. & - (reverseDirection.eq.ESMF_DIRECTION_REVERSE).and. & - ESMF_ClockIsReverse(clock2), & - name, failMsg, result, ESMF_SRCLINE) - - !print *, "nring = ", nring, " nclock = ", nclock - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - - call ESMF_AlarmDestroy(alarm4, rc=rc) - call ESMF_ClockDestroy(clock2, rc=rc) - - ! ---------------------------------------------------------------------------- - - !EX_UTest - !Test Sticky Alarms 1 - ! Test reverse sticky alarm - write(failMsg, *) " Did not return nstep=2 and ESMF_SUCCESS" - write(name, *) "Sticky Alarm Test 1" - call ESMF_TimeIntervalSet(timeStep, m=15, rc=rc) - call ESMF_TimeSet(startTime, yy=1999, mm=12, dd=31, h=23, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeSet(stopTime, yy=2000, mm=1, dd=1, h=23, & - calendar=gregorianCalendar, rc=rc) - clock2 = ESMF_ClockCreate(timeStep, startTime, stopTime=stopTime, & - name="Clock 2", rc=rc) - call ESMF_TimeSet(alarmTime, yy=2000, mm=1, dd=1, h=1, & - calendar=gregorianCalendar, rc=rc) - alarm4 = ESMF_AlarmCreate(clock=clock2, ringTime=alarmTime, rc=rc) - ! number of clock time steps alarm rings for - nstep = 0 - - ! number of times the clock has been run - nclock = 0 - - do while (nclock < 2) - ! run the clock - do while (.not. ESMF_ClockIsDone(clock2, rc=rc)) - call ESMF_ClockGet(clock2, currTime=currentTime, rc=rc) - call ESMF_TimeGet(currentTime, yy=yy, mm=mm, dd=dd, h=h, m=m, rc=rc) - !print *, mm, "/", dd, "/", yy, " ", h, ":", m - if (ESMF_AlarmIsRinging(alarm4)) then - nstep = nstep + 1 - !print *, "on" - call ESMF_AlarmRingerOff(alarm4, rc=rc) - else - !print *, "off" - endif - call ESMF_ClockAdvance(clock2, rc=rc) - enddo - - call ESMF_ClockSet(clock2, direction=ESMF_DIRECTION_REVERSE, rc=rc) - nclock = nclock + 1 - enddo - - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(nstep.eq.2), & - name, failMsg, result, ESMF_SRCLINE) - - !print *, "nstep = ", nstep, " nclock = ", nclock - - call ESMF_AlarmDestroy(alarm4, rc=rc) - call ESMF_ClockDestroy(clock2, rc=rc) - - ! ---------------------------------------------------------------------------- - - !EX_UTest - !Test Sticky Alarms 2 - ! Test reverse interval sticky alarm - write(failMsg, *) " Did not return nstep=23 and ESMF_SUCCESS" - write(name, *) "Sticky Alarm Test 2" - call ESMF_TimeIntervalSet(timeStep, m=15, rc=rc) - call ESMF_TimeSet(startTime, yy=1999, mm=12, dd=31, h=23, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeSet(stopTime, yy=2000, mm=1, dd=1, h=23, & - calendar=gregorianCalendar, rc=rc) - clock2 = ESMF_ClockCreate(timeStep, startTime, stopTime=stopTime, & - name="Clock 2", rc=rc) - call ESMF_TimeSet(alarmTime, yy=2000, mm=1, dd=1, h=1, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeIntervalSet(alarmStep, h=2, rc=rc) - alarm4 = ESMF_AlarmCreate(clock=clock2, ringTime=alarmTime, & - ringInterval=alarmStep, rc=rc) - ! number of clock time steps alarm rings for - nstep = 0 - - ! number of times the clock has been run - nclock = 0 - - do while (nclock < 2) - ! run the clock - do while (.not. ESMF_ClockIsDone(clock2, rc=rc)) - call ESMF_ClockGet(clock2, currTime=currentTime, rc=rc) - call ESMF_TimeGet(currentTime, yy=yy, mm=mm, dd=dd, h=h, m=m, rc=rc) - !print *, mm, "/", dd, "/", yy, " ", h, ":", m - if (ESMF_AlarmIsRinging(alarm4)) then - nstep = nstep + 1 - !print *, "on" - call ESMF_AlarmRingerOff(alarm4, rc=rc) - else - !print *, "off" - endif - call ESMF_ClockAdvance(clock2, rc=rc) - enddo - - call ESMF_ClockSet(clock2, direction=ESMF_DIRECTION_REVERSE, rc=rc) - nclock = nclock + 1 - enddo - - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(nstep.eq.23), & - name, failMsg, result, ESMF_SRCLINE) - - !print *, "nstep = ", nstep, " nclock = ", nclock - - call ESMF_AlarmDestroy(alarm4, rc=rc) - call ESMF_ClockDestroy(clock2, rc=rc) - - ! ---------------------------------------------------------------------------- - - !EX_UTest - !Test Sticky Alarms 3 - ! Test reverse one-shot sticky alarms per WRF use case - ! From Tom Henderson/WRF - - write(name, *) "Sticky Alarm Test 3" - write(failMsg, *) " Alarms did not turn on/off at the correct time/iteration or did not return ESMF_SUCCESS" - - call ESMF_TimeIntervalSet(timeStep, h=1, rc=rc) - call ESMF_TimeSet(startTime, yy=2005, mm=6, dd=15, h=1, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeSet(stopTime, yy=2005, mm=6, dd=15, h=5, & - calendar=gregorianCalendar, rc=rc) - domainClock = ESMF_ClockCreate(timeStep, startTime, stopTime=stopTime, & - name="WRF Clock", rc=rc) - - call ESMF_TimeSet(beforeAlarmTime, yy=2005, mm=6, dd=15, h=2, & - calendar=gregorianCalendar, rc=rc) - beforeAlarm = ESMF_AlarmCreate(clock=domainClock, & - ringTime=beforeAlarmTime, rc=rc) - - call ESMF_TimeSet(afterAlarmTime, yy=2005, mm=6, dd=15, h=3, & - calendar=gregorianCalendar, rc=rc) - afterAlarm = ESMF_AlarmCreate(clock=domainClock, & - ringTime=afterAlarmTime, rc=rc) - - ! any single failure will cause the whole test to fail - testPass = .true. - - ! track loop iterations - iteration = 0 - - call ESMF_ClockGet(domainClock, currTime=currentTime, rc=rc) - call ESMF_TimeGet(currentTime, yy=yy, mm=mm, dd=dd, h=h, rc=rc) - !print *, "Begin" - !print *, mm, "/", dd, "/", yy, " ", h, ": 0" - - ! run the clock forward - do while (.not. ESMF_ClockIsDone(domainClock, rc=rc)) - iteration = iteration + 1 - !print *, "Iteration = ", iteration - - if (ESMF_AlarmIsRinging(beforeAlarm, rc=rc)) then - if (iteration .ne. 2 .or. h .ne. 2) then - testPass = .false. - endif - !print *, " beforeAlarm on" - call ESMF_AlarmRingerOff(beforeAlarm, rc=rc) - else - !print *, " beforeAlarm off" - endif - - ! would call WRF solver here, before clock advance - !print *, " Solve" - - call ESMF_ClockAdvance(domainClock, rc=rc) - call ESMF_ClockGet(domainClock, currTime=currentTime, rc=rc) - call ESMF_TimeGet(currentTime, yy=yy, mm=mm, dd=dd, h=h, rc=rc) - !print *, " ClockAdvance()" - !print *, mm, "/", dd, "/", yy, " ", h, ": 0" - - if (ESMF_AlarmIsRinging(afterAlarm, rc=rc)) then - if (iteration .ne. 2 .or. h .ne. 3) then - testPass = .false. - endif - !print *, " afterAlarm on" - call ESMF_AlarmRingerOff(afterAlarm, rc=rc) - else - !print *, " afterAlarm off" - endif - enddo - - ! run the clock backwards - call ESMF_ClockSet(domainClock, direction=ESMF_DIRECTION_REVERSE, rc=rc) - !print * - !print *, "domainClock set in reverse" - !print * - - do while (.not. ESMF_ClockIsDone(domainClock, rc=rc)) - !print *, "Iteration = ", iteration - - if (ESMF_AlarmIsRinging(afterAlarm, rc=rc)) then - if (iteration .ne. 2 .or. h .ne. 3) then - testPass = .false. - endif - !print *, " afterAlarm on" - call ESMF_AlarmRingerOff(afterAlarm, rc=rc) - else - !print *, " afterAlarm off" - endif - - ! advance clock - call ESMF_ClockAdvance(domainClock, rc=rc) - call ESMF_ClockGet(domainClock, currTime=currentTime, rc=rc) - call ESMF_TimeGet(currentTime, yy=yy, mm=mm, dd=dd, h=h, rc=rc) - !print *, " ClockAdvance()" - !print *, mm, "/", dd, "/", yy, " ", h, ": 0" - - ! would call WRF solver here, after clock advance - !print *, " Solve" - - if (ESMF_AlarmIsRinging(beforeAlarm, rc=rc)) then - if (iteration .ne. 2 .or. h .ne. 2) then - testPass = .false. - endif - !print *, " beforeAlarm on" - call ESMF_AlarmRingerOff(beforeAlarm, rc=rc) - else - !print *, " beforeAlarm off" - endif - - iteration = iteration - 1 - enddo - - call ESMF_Test(testPass.and.(rc.eq.ESMF_SUCCESS), & - name, failMsg, result, ESMF_SRCLINE) - - call ESMF_AlarmDestroy(afterAlarm, rc=rc) - call ESMF_AlarmDestroy(beforeAlarm, rc=rc) - call ESMF_ClockDestroy(domainClock, rc=rc) - - ! ---------------------------------------------------------------------------- - - !EX_UTest - !Test Sticky Alarms 4 - ! Test reverse *interval* sticky alarms; variation on WRF use case above - - write(name, *) "Sticky Alarm Test 4" - write(failMsg, *) " Alarms did not turn on/off at the correct time/iteration or did not return ESMF_SUCCESS" - - call ESMF_TimeIntervalSet(timeStep, h=1, rc=rc) - call ESMF_TimeSet(startTime, yy=2005, mm=6, dd=15, h=1, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeSet(stopTime, yy=2005, mm=6, dd=15, h=10, & - calendar=gregorianCalendar, rc=rc) - domainClock = ESMF_ClockCreate(timeStep, startTime, stopTime=stopTime, & - name="WRF Clock", rc=rc) - - call ESMF_TimeSet(beforeAlarmTime, yy=2005, mm=6, dd=15, h=2, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeIntervalSet(alarmStep, h=3, rc=rc) - beforeAlarm = ESMF_AlarmCreate(clock=domainClock, & - ringTime=beforeAlarmTime, & - ringInterval=alarmStep, rc=rc) - - call ESMF_TimeSet(afterAlarmTime, yy=2005, mm=6, dd=15, h=3, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeIntervalSet(alarmStep2, h=2, rc=rc) - afterAlarm = ESMF_AlarmCreate(clock=domainClock, & - ringTime=afterAlarmTime, & - ringInterval=alarmStep2, rc=rc) - - ! any single failure will cause the whole test to fail - testPass = .true. - - ! track loop iterations - iteration = 0 - - call ESMF_ClockGet(domainClock, currTime=currentTime, rc=rc) - call ESMF_TimeGet(currentTime, yy=yy, mm=mm, dd=dd, h=h, rc=rc) - !print *, "Begin" - !print *, mm, "/", dd, "/", yy, " ", h, ": 0" - - ! run the clock forward - do while (.not. ESMF_ClockIsDone(domainClock, rc=rc)) - iteration = iteration + 1 - !print *, "Iteration = ", iteration - - if (ESMF_AlarmIsRinging(beforeAlarm, rc=rc)) then - if ((iteration .ne. 2 .or. h .ne. 2).and. & - (iteration .ne. 5 .or. h .ne. 5).and. & - (iteration .ne. 8 .or. h .ne. 8)) then - testPass = .false. - endif - !print *, " beforeAlarm on" - call ESMF_AlarmRingerOff(beforeAlarm, rc=rc) - else - !print *, " beforeAlarm off" - endif - - ! would call WRF solver here, before clock advance - !print *, " Solve" - - call ESMF_ClockAdvance(domainClock, rc=rc) - call ESMF_ClockGet(domainClock, currTime=currentTime, rc=rc) - call ESMF_TimeGet(currentTime, yy=yy, mm=mm, dd=dd, h=h, rc=rc) - !print *, " ClockAdvance()" - !print *, mm, "/", dd, "/", yy, " ", h, ": 0" - - if (ESMF_AlarmIsRinging(afterAlarm, rc=rc)) then - if ((iteration .ne. 2 .or. h .ne. 3).and. & - (iteration .ne. 4 .or. h .ne. 5).and. & - (iteration .ne. 6 .or. h .ne. 7).and. & - (iteration .ne. 8 .or. h .ne. 9)) then - testPass = .false. - endif - !print *, " afterAlarm on" - call ESMF_AlarmRingerOff(afterAlarm, rc=rc) - else - !print *, " afterAlarm off" - endif - enddo - - ! run the clock backwards - call ESMF_ClockSet(domainClock, direction=ESMF_DIRECTION_REVERSE, rc=rc) - !print * - !print *, "domainClock set in reverse" - !print * - - do while (.not. ESMF_ClockIsDone(domainClock, rc=rc)) - !print *, "Iteration = ", iteration - - if (ESMF_AlarmIsRinging(afterAlarm, rc=rc)) then - if ((iteration .ne. 2 .or. h .ne. 3).and. & - (iteration .ne. 4 .or. h .ne. 5).and. & - (iteration .ne. 6 .or. h .ne. 7).and. & - (iteration .ne. 8 .or. h .ne. 9)) then - testPass = .false. - endif - !print *, " afterAlarm on" - call ESMF_AlarmRingerOff(afterAlarm, rc=rc) - else - !print *, " afterAlarm off" - endif - - ! advance clock - call ESMF_ClockAdvance(domainClock, rc=rc) - call ESMF_ClockGet(domainClock, currTime=currentTime, rc=rc) - call ESMF_TimeGet(currentTime, yy=yy, mm=mm, dd=dd, h=h, rc=rc) - !print *, " ClockAdvance()" - !print *, mm, "/", dd, "/", yy, " ", h, ": 0" - - ! would call WRF solver here, after clock advance - !print *, " Solve" - - if (ESMF_AlarmIsRinging(beforeAlarm, rc=rc)) then - if ((iteration .ne. 2 .or. h .ne. 2).and. & - (iteration .ne. 5 .or. h .ne. 5).and. & - (iteration .ne. 8 .or. h .ne. 8)) then - testPass = .false. - endif - !print *, " beforeAlarm on" - call ESMF_AlarmRingerOff(beforeAlarm, rc=rc) - else - !print *, " beforeAlarm off" - endif - - iteration = iteration - 1 - enddo - - call ESMF_Test(testPass.and.(rc.eq.ESMF_SUCCESS), & - name, failMsg, result, ESMF_SRCLINE) - - call ESMF_AlarmDestroy(afterAlarm, rc=rc) - call ESMF_AlarmDestroy(beforeAlarm, rc=rc) - call ESMF_ClockDestroy(domainClock, rc=rc) - - ! ---------------------------------------------------------------------------- - - !EX_UTest - !Test Sticky Alarms 5 - ! Test delay in checking for ringing sticky alarms, - ! from James Geiger in #2825456, case #2 in his alarm_test.f90 reproducer - write(name, *) "Sticky Alarm Test 5" - write(failMsg, *) " Alarm did not ring at the correct times or did not return ESMF_SUCCESS" - call ESMF_TimeIntervalSet(timeStep, s=3600, rc=rc) - call ESMF_TimeSet(startTime, yy=2000, mm=1, dd=1, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeSet(stopTime, yy=2000, mm=1, dd=3, & - calendar=gregorianCalendar, rc=rc) - clock2 = ESMF_ClockCreate(timeStep, startTime, stopTime=stopTime, & - name="Clock", rc=rc) - call ESMF_TimeSet(alarmTime, yy=2000, mm=1, dd=1, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeIntervalSet(alarmStep, h=3, rc=rc) - alarmTime = alarmTime + alarmStep - alarm4 = ESMF_AlarmCreate(clock=clock2, ringTime=alarmTime, & - ringInterval=alarmStep, rc=rc) - testPass = .false. - iteration = 0 - nring = 0 - do while (.not.ESMF_ClockIsStopTime(clock2, rc=rc)) - iteration = iteration + 1 - !print *, "clock2 timestep ", iteration - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - if (iteration .eq. 10) then - ! waiting period is over, clear any alarm which may have occurred - if (ESMF_AlarmIsRinging(alarm4, rc=rc)) then - call ESMF_AlarmRingerOff(alarm4, rc=rc) - endif - endif - call ESMF_ClockAdvance(clock2, rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - !call ESMF_ClockPrint(clock2, options="currTime string", rc=rc) - - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - if (iteration .gt. 10) then - ! process any alarm occuring after initial 10 hour waiting period - if (ESMF_AlarmIsRinging(alarm4, rc=rc)) then - nring = nring + 1 - !print *, "alarm4 is ringing!" - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - call ESMF_AlarmRingerOff(alarm4, rc=rc) - endif - endif - end do - - ! test in REVERSE mode (not from James) - call ESMF_ClockSet(clock2, direction=ESMF_DIRECTION_REVERSE, rc=rc) - - do while (.not.ESMF_ClockIsDone(clock2, rc=rc)) - iteration = iteration + 1 - !print *, "clock2 timestep ", iteration - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - call ESMF_ClockAdvance(clock2, rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - !call ESMF_ClockPrint(clock2, options="currTime string", rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - if (ESMF_AlarmIsRinging(alarm4, rc=rc)) then - nring = nring + 1 - !print *, "alarm4 is ringing!" - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - call ESMF_AlarmRingerOff(alarm4, rc=rc) - endif - end do - - ! test double back in FORWARD mode (not from James) - call ESMF_ClockSet(clock2, direction=ESMF_DIRECTION_FORWARD, rc=rc) - - do while (.not.ESMF_ClockIsDone(clock2, rc=rc)) - iteration = iteration + 1 - !print *, "clock2 timestep ", iteration - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - call ESMF_ClockAdvance(clock2, rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - !call ESMF_ClockPrint(clock2, options="currTime string", rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - if (ESMF_AlarmIsRinging(alarm4, rc=rc)) then - nring = nring + 1 - !print *, "alarm4 is ringing!" - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - call ESMF_AlarmRingerOff(alarm4, rc=rc) - endif - end do - - !print *, "alarm4 rang ", nring, " times, clock stepped ", iteration, " times." - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - if (nring.eq.44 .and. iteration.eq.144) testPass = .true. - call ESMF_Test(testPass.and.(rc.eq.ESMF_SUCCESS), & - name, failMsg, result, ESMF_SRCLINE) - - call ESMF_AlarmDestroy(alarm4, rc=rc) - call ESMF_ClockDestroy(clock2, rc=rc) - - ! ---------------------------------------------------------------------------- - - !EX_UTest - !Test Sticky Alarms 6 - ! Test timeStep == ringInterval, from James Geiger in #2910203 - write(name, *) "Sticky Alarm Test 6" - write(failMsg, *) " Alarm did not ring at the correct times or did not return ESMF_SUCCESS" - call ESMF_TimeIntervalSet(timeStep, s=900, rc=rc) - call ESMF_TimeSet(startTime, yy=2003, mm=9, dd=1, & - calendar=gregorianCalendar, rc=rc) - ! dd=3, instead of original 30 in Jims report, to shorten test run time - call ESMF_TimeSet(stopTime, yy=2003, mm=9, dd=3, & - calendar=gregorianCalendar, rc=rc) - clock2 = ESMF_ClockCreate(timeStep, startTime, stopTime=stopTime, & - name="The Clock", rc=rc) - call ESMF_TimeSet(alarmTime, yy=2003, mm=9, dd=1, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeIntervalSet(alarmStep, s=900, rc=rc) - alarm4 = ESMF_AlarmCreate(clock=clock2, ringTime=alarmTime, & - ringInterval=alarmStep, rc=rc) - testPass = .false. - iteration = 0 - nring = 0 - do while (.not.ESMF_ClockIsStopTime(clock2, rc=rc)) - iteration = iteration + 1 - !print *, "clock2 timestep ", iteration - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - call ESMF_ClockAdvance(clock2, rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - !call ESMF_ClockPrint(clock2, options="currTime string", rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - if (ESMF_AlarmIsRinging(alarm4, rc=rc)) then - nring = nring + 1 - !print *, "alarm4 is ringing!" - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - call ESMF_AlarmRingerOff(alarm4, rc=rc) - endif - end do - - ! test in REVERSE mode (not from James) - call ESMF_ClockSet(clock2, direction=ESMF_DIRECTION_REVERSE, rc=rc) - - do while (.not.ESMF_ClockIsDone(clock2, rc=rc)) - iteration = iteration + 1 - !print *, "clock2 timestep ", iteration - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - call ESMF_ClockAdvance(clock2, rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - !call ESMF_ClockPrint(clock2, options="currTime string", rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - if (ESMF_AlarmIsRinging(alarm4, rc=rc)) then - nring = nring + 1 - !print *, "alarm4 is ringing!" - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - call ESMF_AlarmRingerOff(alarm4, rc=rc) - endif - end do - - ! test double back in FORWARD mode (not from James), - call ESMF_ClockSet(clock2, direction=ESMF_DIRECTION_FORWARD, rc=rc) - - do while (.not.ESMF_ClockIsDone(clock2, rc=rc)) - iteration = iteration + 1 - !print *, "clock2 timestep ", iteration - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - call ESMF_ClockAdvance(clock2, rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - !call ESMF_ClockPrint(clock2, options="currTime string", rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - if (ESMF_AlarmIsRinging(alarm4, rc=rc)) then - nring = nring + 1 - !print *, "alarm4 is ringing!" - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - call ESMF_AlarmRingerOff(alarm4, rc=rc) - endif - end do - - !print *, "alarm4 rang ", nring, " times, clock stepped ", iteration, " times." - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - if (nring.eq.576 .and. iteration.eq.576) testPass = .true. - call ESMF_Test(testPass.and.(rc.eq.ESMF_SUCCESS), & - name, failMsg, result, ESMF_SRCLINE) - - call ESMF_AlarmDestroy(alarm4, rc=rc) - call ESMF_ClockDestroy(clock2, rc=rc) - - ! ---------------------------------------------------------------------------- - - !EX_UTest - !Test Sticky Alarms 7 - ! Test timeStep > ringInterval, inspired by James Geiger in #2910203 - write(name, *) "Sticky Alarm Test 7" - write(failMsg, *) " Alarm did not ring at the correct times or did not return ESMF_SUCCESS" - call ESMF_TimeIntervalSet(timeStep, s=1800, rc=rc) - call ESMF_TimeSet(startTime, yy=2003, mm=9, dd=1, & - calendar=gregorianCalendar, rc=rc) - ! dd=3, instead of original 30 in Jims report, to save test run time - call ESMF_TimeSet(stopTime, yy=2003, mm=9, dd=3, & - calendar=gregorianCalendar, rc=rc) - clock2 = ESMF_ClockCreate(timeStep, startTime, stopTime=stopTime, & - name="The Clock", rc=rc) - call ESMF_TimeSet(alarmTime, yy=2003, mm=9, dd=1, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeIntervalSet(alarmStep, s=900, rc=rc) - alarm4 = ESMF_AlarmCreate(clock=clock2, ringTime=alarmTime, & - ringInterval=alarmStep, rc=rc) - testPass = .false. - iteration = 0 - nring = 0 - do while (.not.ESMF_ClockIsStopTime(clock2, rc=rc)) - iteration = iteration + 1 - !print *, "clock2 timestep ", iteration - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - call ESMF_ClockAdvance(clock2, rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - !call ESMF_ClockPrint(clock2, options="currTime string", rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - if (ESMF_AlarmIsRinging(alarm4, rc=rc)) then - nring = nring + 1 - !print *, "alarm4 is ringing!" - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - call ESMF_AlarmRingerOff(alarm4, rc=rc) - endif - !call ESMF_AlarmPrint(alarm4, options="ringtime string", rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - end do - !print *, "At end of 1st forward run, nring = ", nring - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - - ! TODO: test in REVERSE mode (not from James) - ! currently doesn't ring in REVERSE - call ESMF_ClockSet(clock2, direction=ESMF_DIRECTION_REVERSE, rc=rc) - - do while (.not.ESMF_ClockIsDone(clock2, rc=rc)) - iteration = iteration + 1 - !print *, "clock2 timestep ", iteration - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - call ESMF_ClockAdvance(clock2, rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - !call ESMF_ClockPrint(clock2, options="currTime string", rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - if (ESMF_AlarmIsRinging(alarm4, rc=rc)) then - nring = nring + 1 - !print *, "alarm4 is ringing!" - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - call ESMF_AlarmRingerOff(alarm4, rc=rc) - endif - !call ESMF_AlarmPrint(alarm4, options="ringtime string", rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - end do - !print *, "At end of reverse run, nring = ", nring - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - - ! TODO: test double back in FORWARD mode (not from James) - ! currently doesn't work until back into day 2 - call ESMF_ClockSet(clock2, direction=ESMF_DIRECTION_FORWARD, rc=rc) - - do while (.not.ESMF_ClockIsDone(clock2, rc=rc)) - iteration = iteration + 1 - !print *, "clock2 timestep ", iteration - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - call ESMF_ClockAdvance(clock2, rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - !call ESMF_ClockPrint(clock2, options="currTime string", rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - if (ESMF_AlarmIsRinging(alarm4, rc=rc)) then - nring = nring + 1 - !print *, "alarm4 is ringing!" - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - call ESMF_AlarmRingerOff(alarm4, rc=rc) - endif - !call ESMF_AlarmPrint(alarm4, options="ringtime string", rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - end do - !print *, "At end of 2nd forward run, nring = ", nring - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - - !print *, "alarm4 rang ", nring, " times, clock stepped ", iteration, " times." - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - if (nring.eq.288 .and. iteration.eq.288) testPass = .true. - call ESMF_Test(testPass.and.(rc.eq.ESMF_SUCCESS), & - name, failMsg, result, ESMF_SRCLINE) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - - call ESMF_AlarmDestroy(alarm4, rc=rc) - call ESMF_ClockDestroy(clock2, rc=rc) - - ! ---------------------------------------------------------------------------- - - !EX_UTest - !Test Fractional Time Alarms 1 - write(failMsg, *) " Did not return nstep=8, and ESMF_SUCCESS" - write(name, *) "Fractional Time Alarm Test 1" - call ESMF_TimeIntervalSet(timeStep, ms=10, rc=rc) - call ESMF_TimeIntervalSet(alarmStep, ms=100, rc=rc) - call ESMF_TimeSet(startTime, yy=1999, mm=12, dd=31, h=23, m=59, s=59, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeSet(stopTime, yy=2000, mm=1, dd=1, & - calendar=gregorianCalendar, rc=rc) - clock2=ESMF_ClockCreate(timeStep, startTime, stopTime=stopTime, & - name="Clock 2", rc=rc) - call ESMF_TimeSet(alarmTime, yy=1999, mm=12, dd=31, h=23, m=59, s=59, & - ms=200, calendar=gregorianCalendar, rc=rc) - alarm4 = ESMF_AlarmCreate(clock=clock2, ringTime=alarmTime, & - ringInterval=alarmStep, rc=rc) - - ! number of clock time steps alarm rings for - nstep = 0 - - ! run the clock - do while (.not. ESMF_ClockIsStopTime(clock2, rc=rc)) - if (ESMF_AlarmIsRinging(alarm4)) then - nstep = nstep + 1 - call ESMF_AlarmRingerOff(alarm4) - endif - call ESMF_ClockAdvance(clock2, rc=rc) - enddo - - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(nstep.eq.8), & - name, failMsg, result, ESMF_SRCLINE) - - call ESMF_AlarmDestroy(alarm4, rc=rc) - call ESMF_ClockDestroy(clock2, rc=rc) - - ! ---------------------------------------------------------------------------- - - !EX_UTest - !Test Fractional Time Alarms 2 - write(failMsg, *) " Did not return nstep=4, and ESMF_SUCCESS" - write(name, *) "Fractional Time Alarm Test 2" - call ESMF_TimeIntervalSet(timeStep, sN=-22, sD=7, rc=rc) - call ESMF_TimeIntervalSet(alarmStep, sN=-44, sD=7, rc=rc) - call ESMF_TimeSet(startTime, yy=2000, mm=1, dd=1, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeSet(stopTime, yy=1999, mm=12, dd=31, h=23, m=59, s=28, & - sN=4, sD=7, calendar=gregorianCalendar, rc=rc) - clock2=ESMF_ClockCreate(timeStep, startTime, stopTime=stopTime, & - name="Clock 2", rc=rc) - call ESMF_TimeSet(alarmTime, yy=1999, mm=12, dd=31, h=23, m=59, s=53, & - sN=2, sD=7, calendar=gregorianCalendar, rc=rc) - alarm4 = ESMF_AlarmCreate(clock=clock2, ringTime=alarmTime, & - ringInterval=alarmStep, rc=rc) - - !print *, "stopTime = " - !call ESMF_TimePrint(stopTime) - !print *, "alarmTime = " - !call ESMF_TimePrint(alarmTime) - !print *, "timeStep = " - !call ESMF_TimeIntervalPrint(timeStep) - !print *, "alarmStep = " - !call ESMF_TimeIntervalPrint(alarmStep) - - ! number of clock time steps alarm rings for - nstep = 0 - - ! run the clock - do while (.not. ESMF_ClockIsStopTime(clock2, rc=rc)) - if (ESMF_AlarmIsRinging(alarm4)) then - nstep = nstep + 1 - call ESMF_AlarmRingerOff(alarm4) - endif - call ESMF_ClockAdvance(clock2, rc=rc) - enddo - - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(nstep.eq.4), & - name, failMsg, result, ESMF_SRCLINE) - - call ESMF_AlarmDestroy(alarm4, rc=rc) - call ESMF_ClockDestroy(clock2, rc=rc) - - ! ---------------------------------------------------------------------------- - - !EX_UTest - !Test Alarm ringTime = clock startTime => should ring immediately - ! upon alarm creation. - write(failMsg, *) " Did not return alarm ringing and ESMF_SUCCESS" - write(name, *) "Test Alarm ringTime = Clock startTime" - call ESMF_TimeIntervalSet(timeStep, ms=10, rc=rc) - call ESMF_TimeSet(startTime, yy=1999, mm=12, dd=31, h=23, m=59, s=59, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeSet(stopTime, yy=2000, mm=1, dd=1, & - calendar=gregorianCalendar, rc=rc) - clock2=ESMF_ClockCreate(timeStep, startTime, stopTime=stopTime, & - name="Clock 2", rc=rc) - alarm4 = ESMF_AlarmCreate(clock=clock2, ringTime=startTime, rc=rc) - - bool = ESMF_AlarmIsRinging(alarm4) - - call ESMF_Test((bool.and.rc.eq.ESMF_SUCCESS), & - name, failMsg, result, ESMF_SRCLINE) - - call ESMF_AlarmDestroy(alarm4, rc=rc) - call ESMF_ClockDestroy(clock2, rc=rc) - - ! ---------------------------------------------------------------------------- - - !EX_UTest - !Test Alarm ringTime = clock startTime *and* ringInterval specified - ! upon alarm creation => should ring immediately. Test 1 - ! From Tom Black in Support ticket 1989990. - write(failMsg, *) " Did not return alarm ringing and ESMF_SUCCESS" - write(name, *) "Alarm ringTime = Clock startTime with ringInterval, test 1" - call ESMF_TimeIntervalSet(timeStep, m=2, rc=rc) - call ESMF_TimeIntervalSet(alarmStep, s=60, rc=rc) - call ESMF_TimeSet(startTime, yy=2007, mm=9, dd=18, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeSet(stopTime, yy=2007, mm=9, dd=19, & - calendar=gregorianCalendar, rc=rc) - clock2=ESMF_ClockCreate(timeStep, startTime, stopTime=stopTime, & - name="Clock 2", rc=rc) - alarm4 = ESMF_AlarmCreate(clock=clock2, ringTime=startTime, & - ringInterval=alarmStep, rc=rc) - - call ESMF_AlarmGet(alarm4, ringTime=alarmTime, rc=rc) - bool = ESMF_AlarmIsRinging(alarm4) - - call ESMF_Test(((alarmTime==startTime+alarmStep).and.bool.and. & - rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) - - call ESMF_AlarmDestroy(alarm4, rc=rc) - call ESMF_ClockDestroy(clock2, rc=rc) - - ! ---------------------------------------------------------------------------- - - !EX_UTest - !Test Alarm ringTime = clock startTime *and* ringInterval specified - ! upon alarm creation => should ring immediately. Test 2 - ! From Tom Black in Support ticket 1989990. - write(failMsg, *) " Did not return alarm ringing 21 times and ESMF_SUCCESS" - write(name, *) "Alarm ringTime = Clock startTime with ringInterval, test 2" - - ! any single failure will cause the whole test to fail - testPass = .true. - - call ESMF_TimeIntervalSet(timeStep, s=60, rc=rc) - call ESMF_TimeIntervalSet(runDuration, s=3600, rc=rc) - call ESMF_TimeIntervalSet(alarmStep, s=180, rc=rc) - call ESMF_TimeSet(startTime, yy=2007, mm=9, dd=18, & - calendar=gregorianCalendar, rc=rc) - clock2=ESMF_ClockCreate(timeStep, startTime, & - runDuration=runDuration, name="Clock 2", rc=rc) - - ! Tom Black's AlarmCreate() ... - alarm4=ESMF_AlarmCreate( & - name ='ALARM Recv from Parent' & !<-- Name of Alarm - ,clock =clock2 & !<-- Each domain's ATM Driver Clock - ,ringTime =startTime & !<-- First time the Alarm rings (ESMF) - ,ringInterval =alarmStep & !<-- Recv from my parent at this - ! frequency (ESMF) - ,ringTimeStepCount=1 & !<-- The Alarm rings for this many - ! timesteps - ,sticky =.false. & !<-- Alarm does not ring until turned off - ,rc =rc) - - ! run the clock - ringCount = 0 - do while (.not. ESMF_ClockIsStopTime(clock2, rc=rc)) - call ESMF_ClockGet(clock2, advanceCount=forwardCount, rc=rc) - !print *, "At clock timestep #", forwardCount - - call ESMF_AlarmGet(alarm4, clock=clock1, rc=rc) - call ESMF_ClockGet(clock1, currTime=currentTime2, rc=rc) - !print *, "Alarm's clock's currTime ..." - !call ESMF_TimePrint(currentTime2, options="string", rc=rc) - if (clock2 /= clock1) then - testPass = .false. - !print *, "Alarm's clock and domain clock are *not* the same" - endif - - call ESMF_ClockGet(clock2, currTime=currentTime, prevTime=prevTime, & - rc=rc) - !print *, "Clock's currTime and prevTime ..." - !call ESMF_TimePrint(currentTime, options="string", rc=rc) - !call ESMF_TimePrint(prevTime, options="string", rc=rc) - - if (currentTime /= currentTime2) then - testPass = .false. - !print *, "Alarm's clock's currTime is *not* the same as the domain clock's currTime" - endif - - call ESMF_AlarmGet(alarm4, ringTime=alarmTime, rc=rc) - !print *, "Alarm's ringTime ..." - !call ESMF_TimePrint(alarmTime, options="string", rc=rc) - - if (ESMF_AlarmIsRinging(alarm=alarm4, rc=rc)) then - ringCount = ringCount + 1 - !print *, " Alarm is ringing" - if (alarmTime /= currentTime+alarmStep) then - testPass = .false. - !print *, " Alarm ringTime *not* equal to clock currTime + alarmStep" - endif - endif - call ESMF_ClockAdvance(clock2, rc=rc) - enddo - - call ESMF_ClockGet(clock2, advanceCount=forwardCount, rc=rc) - !print *, "End of clock run: At clock timestep #", forwardCount - if (ESMF_AlarmIsRinging(alarm=alarm4, rc=rc)) then - !print *, " Alarm is ringing" - ringCount = ringCount + 1 - endif - - ! Alarm should have rung 21 times, including from timestep 0 (upon alarm - ! creation) through timestep 60 (end of clock run) inclusive. - ! Final ringTime should be one alarmStep past the clock end time. - call ESMF_AlarmGet(alarm4, ringTime=alarmTime, rc=rc) - call ESMF_Test(((alarmTime==startTime+runDuration+alarmStep).and. & - ringCount==21.and.testPass.and. & - rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) - !print *, "Alarm rang ", ringCount, " times." - !print *, "Alarm's final ringTime, after final clockAdvance() ..." - !call ESMF_TimePrint(alarmTime, options="string", rc=rc) - - call ESMF_AlarmDestroy(alarm4, rc=rc) - call ESMF_ClockDestroy(clock2, rc=rc) - - ! ---------------------------------------------------------------------------- - - !EX_UTest - !Test Alarm ringTime = clock startTime *and* ringInterval specified - ! upon alarm creation => should ring immediately. Test 3, test REVERSE - ! back to clock starttime. Robustness test for solution to - ! Tom Black problem in Support ticket 1989990. - write(failMsg, *) " Did not return alarm ringing 41 times and ESMF_SUCCESS" - write(name, *) "Alarm ringTime = Clock startTime with ringInterval, test 3 (reverse)" - - call ESMF_TimeIntervalSet(timeStep, s=60, rc=rc) - call ESMF_TimeIntervalSet(runDuration, s=3600, rc=rc) - call ESMF_TimeIntervalSet(alarmStep, s=180, rc=rc) - call ESMF_TimeSet(startTime, yy=2007, mm=9, dd=18, & - calendar=gregorianCalendar, rc=rc) - clock2=ESMF_ClockCreate(timeStep, startTime, & - runDuration=runDuration, name="Clock 2", rc=rc) - - ! like Tom Black's AlarmCreate(), but sticky - alarm4=ESMF_AlarmCreate( & - name ='ALARM Recv from Parent' & !<-- Name of Alarm - ,clock =clock2 & !<-- Each domain's ATM Driver Clock - ,ringTime =startTime & !<-- First time the Alarm rings (ESMF) - ,ringInterval =alarmStep & !<-- Recv from my parent at this - ! frequency (ESMF) - ,rc =rc) - - ! number of clock time steps alarm rings for - nring = 0 - - ! number of times the clock has been run - nclock = 0 - - do while (nclock < 2) - ! run the clock - do while (.not. ESMF_ClockIsDone(clock2, rc=rc)) - if (ESMF_AlarmIsRinging(alarm4)) then - nring = nring + 1 - !print *, "on" - call ESMF_AlarmRingerOff(alarm4, rc=rc) - else - !print *, "off" - endif - call ESMF_ClockAdvance(clock2, rc=rc) - enddo - - if (nclock.eq.0) then - call ESMF_ClockGet(clock2, direction=forwardDirection, & - advanceCount=forwardCount, rc=rc) - !print *, "forwardCount = ", forwardCount - else - call ESMF_ClockGet(clock2, direction=reverseDirection, & - advanceCount=reverseCount, rc=rc) - !print *, "reverseCount = ", reverseCount - endif - - call ESMF_ClockSet(clock2, direction=ESMF_DIRECTION_REVERSE, rc=rc) - nclock = nclock + 1 - enddo - - ! count ring at the end point - if (ESMF_AlarmIsRinging(alarm4)) then - nring = nring + 1 - !print *, "on" - call ESMF_AlarmRingerOff(alarm4, rc=rc) - else - !print *, "off" - endif - - call ESMF_Test((rc.eq.ESMF_SUCCESS).and.(nring.eq.41).and. & - (forwardCount.eq.60).and.(reverseCount.eq.0).and. & - (forwardDirection.eq.ESMF_DIRECTION_FORWARD).and. & - (reverseDirection.eq.ESMF_DIRECTION_REVERSE).and. & - ESMF_ClockIsReverse(clock2), & - name, failMsg, result, ESMF_SRCLINE) - - !print *, "nring = ", nring, " nclock = ", nclock - - call ESMF_AlarmDestroy(alarm4, rc=rc) - call ESMF_ClockDestroy(clock2, rc=rc) - - ! ---------------------------------------------------------------------------- - - !EX_UTest - !Test Alarm ringTime = clock startTime *and* ringInterval specified - ! upon alarm creation *and* after clock restored from restart state -- - ! with 2 calls to ESMF_ClockSet() -- should ring immediately. - ! This approach to restart will become obsolete with the implementation - ! of WriteRestart()/ReadStart(), but it should remain technically valid, - ! along with this unit test. From Ratko Vasic in ticket #2685243. - - write(failMsg, *) " Did not return alarm ringing and ESMF_SUCCESS" - write(name, *) "Alarm ringTime = Clock startTime with ringInterval, after clock restore" - - call ESMF_TimeIntervalSet(timeStep, m=3, rc=rc) - call ESMF_TimeIntervalSet(TIMEINTERVAL_HISTORY, h=3, rc=rc) - call ESMF_TimeSet(startTime, mm=9, dd=18, yy=2007, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeSet(stopTime, mm=9, dd=19, yy=2007, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeSet(currTime, mm=9, dd=18, yy=2007, h=12, & - calendar=gregorianCalendar, rc=rc) - - CLOCK_ATM=ESMF_ClockCreate( & - name ='CLOCK_ATM' & !<-- The ATM Clock's name - ,timeStep =timeStep & !<-- The fundamental timestep in - ! this component - ,startTime =startTime & !<-- Start time of simulation - ,stopTime =stopTime & !<-- Stop time of simulation - ,rc =rc) - - ! 1st ClockSet() to reset currTime and advanceCount for restart - call ESMF_ClockSet( & - clock =CLOCK_ATM & !<-- The ATM Component's Clock - ,currtime =currTime & !<-- Current time of simulation - ,advanceCount=240_ESMF_KIND_I8 & !<-- Timestep at this current time - ,rc =rc) - - ! 2nd ClockSet() with same values that CLOCK_ATM already has; should - ! have no affect - call ESMF_ClockSet(clock =CLOCK_ATM & - ,currtime =currTime & - ,starttime=startTime & - ,rc =rc) - - !call ESMF_ClockPrint(CLOCK_ATM, rc=rc) - - ALARM_HISTORY=ESMF_AlarmCreate( & - name ='ALARM_HISTORY' & - ,clock =CLOCK_ATM & ! <-- ATM Clock - ,ringTime =currTime & ! <-- Forecast/Restart start - ! time (ESMF) - ,ringInterval =TIMEINTERVAL_HISTORY & ! <-- Time interval between - ,ringTimeStepCount=1 & ! <-- The Alarm rings for - ! this many timesteps - ,sticky =.false. & ! <-- Alarm does not ring - ! until turned off - ,rc =rc) - - !call ESMF_AlarmPrint(ALARM_HISTORY, rc=rc) - - call ESMF_AlarmGet(ALARM_HISTORY, ringTime=alarmTime, rc=rc) - bool = ESMF_AlarmIsRinging(ALARM_HISTORY) - - call ESMF_Test(((alarmTime==currTime+TIMEINTERVAL_HISTORY).and.bool & - .and. rc.eq.ESMF_SUCCESS), & - name, failMsg, result, ESMF_SRCLINE) - - call ESMF_AlarmDestroy(ALARM_HISTORY, rc=rc) - call ESMF_ClockDestroy(CLOCK_ATM, rc=rc) - - ! ---------------------------------------------------------------------------- - - !EX_UTest - !Test Alarm list re-allocation within clock, part 1 - write(failMsg, *) " Did not return ESMF_SUCCESS" - write(name, *) "Alarm list reallocation Test 1" - call ESMF_TimeIntervalSet(timeStep, ms=10, rc=rc) - call ESMF_TimeIntervalSet(alarmStep, ms=100, rc=rc) - call ESMF_TimeSet(startTime, yy=1999, mm=12, dd=31, h=23, m=59, s=59, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeSet(stopTime, yy=2000, mm=1, dd=1, & - calendar=gregorianCalendar, rc=rc) - clock2=ESMF_ClockCreate(timeStep, startTime, stopTime=stopTime, & - name="Clock 2", rc=rc) - call ESMF_TimeSet(alarmTime, yy=1999, mm=12, dd=31, h=23, m=59, s=59, & - ms=200, calendar=gregorianCalendar, rc=rc) - - ! fill up clock's alarmList - do i=1,200 - alarm5(i) = ESMF_AlarmCreate(clock=clock2, ringTime=alarmTime, & - ringInterval=alarmStep, rc=rc) - enddo - - ! add one more alarm than there is space for (200), forcing a - ! reallocation to 400 alarms - ! also, set 201st alarm to be the first to ring upon the 1st timestep - call ESMF_TimeSet(alarmTime, yy=1999, mm=12, dd=31, h=23, m=59, s=59, & - ms=10, calendar=gregorianCalendar, rc=rc) - alarm4 = ESMF_AlarmCreate(name="201st Alarm", clock=clock2, & - ringTime=alarmTime, ringInterval=alarmStep, & - rc=rc) - - ! see if the 201st alarm was successfully added to the clock - call ESMF_Test((rc.eq.ESMF_SUCCESS), & - name, failMsg, result, ESMF_SRCLINE) - - ! ---------------------------------------------------------------------------- - - !EX_UTest - !Test Alarm list re-allocation within clock, part 2 - write(failMsg, *) " Did not return 201 alarms and name '201st Alarm'" - write(name, *) "Alarm list reallocation Test 2" - call ESMF_ClockGetAlarmList(clock2, ESMF_ALARMLIST_ALL, & - alarmList=alarmList, & - alarmCount=alarmCount, rc=rc) - write(*,*) "rc=",rc - call ESMF_AlarmGet(alarmList(alarmCount), name=aName, rc=rc) - - !print *, "alarmCount = ", alarmCount - !print *, "201st alarm name = ", aName - write(*,*) "rc=",rc - - ! see if we have 201 alarms and if the 201st alarm has the right name! - call ESMF_Test((alarmCount.eq.201).and.(aName.eq."201st Alarm") & - .and.(rc.eq.ESMF_SUCCESS), & - name, failMsg, result, ESMF_SRCLINE) - - ! ---------------------------------------------------------------------------- - - !EX_UTest - !Test Alarm list re-allocation within clock, part 3 - write(failMsg, *) " Did not return 201st alarm ringing" - write(name, *) "Alarm list reallocation Test 3" - call ESMF_ClockAdvance(clock2, rc=rc) - call ESMF_ClockGetAlarmList(clock2, ESMF_ALARMLIST_RINGING, & - alarmList=alarmList, & - alarmCount=alarmCount, rc=rc) - ! double check ringing with Alarm API call - isringing = ESMF_AlarmIsRinging(alarm4, rc=rc) - - !print *, "alarmCount = ", alarmCount - call ESMF_AlarmGet(alarmList(alarmCount), name=aName, rc=rc) - !print *, "Ringing alarm name = ", trim(aName), ", is ringing = ", & - !isringing - - ! see if the 201st alarm is the only one ringing - call ESMF_Test(isringing.and.(alarmCount.eq.1) & - .and.(aName.eq."201st Alarm") & - .and.(rc.eq.ESMF_SUCCESS), & - name, failMsg, result, ESMF_SRCLINE) - - ! cleanup - do i=1,200 - call ESMF_AlarmDestroy(alarm5(i), rc=rc) - enddo - call ESMF_AlarmDestroy(alarm4, rc=rc) - call ESMF_ClockDestroy(clock2, rc=rc) - - ! ---------------------------------------------------------------------------- - - !EX_UTest - ! Based on reproducer clocktester.F90 from Atanas. See bug #1531948. - write(failMsg, *) " Did not ring enough times during forward/backward march" - write(name, *) "Test ESMF_DIRECTION_FORWARD to a non-sticky alarm " // & - "point, ESMF_DIRECTION_REVERSE, ESMF_DIRECTION_FORWARD" - testPass = .true. - call ESMF_TimeSet (startTime, yy=2009, mm=1, dd=1, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeSet (stopTime, yy=2009, mm=1, dd=2, h=0, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeIntervalSet (timeStep, s=3600, rc=rc) - clock = ESMF_ClockCreate(timeStep, startTime, stopTime=stopTime, & - name="ApplClock", rc=rc) - if (rc /= ESMF_SUCCESS) testPass = .false. - - call ESMF_TimeIntervalSet (alarmStep, s=7200, rc=rc) - !call ESMF_TimeIntervalSet(ringDuration, h=1, rc=rc) - !call ESMF_TimeSet(alarmStopTime, yy=2009, mm=1, dd=1, h=21, & - ! calendar=gregorianCalendar, rc=rc) - alarm1 = ESMF_AlarmCreate (clock=clock, & - ringTime=startTime, ringInterval=alarmStep, & - ! ringDuration=ringDuration, & - ! stopTime=alarmStopTime, & - sticky=.false., name="testAlarm", rc=rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - - !call ESMF_AlarmPrint(alarm1, options="ringduration string", rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - !call ESMF_AlarmPrint(alarm1, options="ringtimestepcount string", rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - - alarmCount = 0 - expectedCount = 22 - do - !print *, "***********************Top of loop 1 **********************" - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - !call ESMF_ClockPrint(clock, options="currtime string", rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - if (ESMF_AlarmIsRinging(alarm1, rc=rc)) then - alarmCount = alarmCount + 1 - !print *, "alarm1 is ringing" - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - !call ESMF_AlarmRingerOff(alarm1, rc=rc) - endif - !call ESMF_AlarmPrint(alarm1, options="ringbegin string", rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - !call ESMF_AlarmPrint(alarm1, options="ringtime string", rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - !call ESMF_AlarmPrint(alarm1, options="ringend string", rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - call ESMF_ClockAdvance(clock, rc=rc) - !call ESMF_AlarmPrint(alarm1, options="ringend string", rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - if (ESMF_ClockIsStopTime(clock, rc=rc)) exit - enddo - !print *, "At end of 1st forward run, alarmCount = ", alarmCount - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - - call ESMF_ClockSet(clock, direction=ESMF_DIRECTION_REVERSE, rc=rc) - - i=0 - do - !print *, "***********************Top of loop 2 **********************" - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - !call ESMF_ClockPrint(clock, options="currtime string", rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - if (ESMF_AlarmIsRinging(alarm1, rc=rc)) then - alarmCount = alarmCount + 1 - !print *, "alarm1 is ringing" - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - !call ESMF_AlarmRingerOff(alarm1, rc=rc) - endif - !call ESMF_AlarmPrint(alarm1, options="ringbegin string", rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - !call ESMF_AlarmPrint(alarm1, options="ringtime string", rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - call ESMF_ClockAdvance(clock, rc=rc) - i = i+1 - if (i == 5) exit - enddo - !print *, "At end of reverse run, alarmCount = ", alarmCount - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - - call ESMF_ClockSet(clock, direction=ESMF_DIRECTION_FORWARD, rc=rc) - - i=0 - do - !print *, "***********************Top of loop 3 **********************" - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - !call ESMF_ClockPrint(clock, options="currtime string", rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - if (ESMF_AlarmIsRinging(alarm1, rc=rc)) then - alarmCount = alarmCount + 1 - !print *, "alarm1 is ringing" - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - !call ESMF_AlarmRingerOff(alarm1, rc=rc) - endif - !call ESMF_AlarmPrint(alarm1, options="ringbegin string", rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - !call ESMF_AlarmPrint(alarm1, options="ringtime string", rc=rc) - !call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - call ESMF_ClockAdvance(clock, rc=rc) - i = i+1 - if (i == 15) exit - enddo - - if (.not. testPass .or. alarmCount /= expectedCount) then - if (.not. testPass) print *, 'bad return codes discovered' - write (failMsg,*) trim (failMsg), ', alarmCount = ', alarmCount, ', expected = ', expectedCount - print *, 'The alarm ringTime may be stuck at:' - call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - call ESMF_AlarmPrint (alarm1, options="ringTime string", rc=rc) - call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - end if - - call ESMF_Test (testPass .and. alarmCount == expectedCount, & - name, failMsg, result, ESMF_SRCLINE) - call ESMF_UtilIOUnitFlush(ESMF_UtilIOStdout) - - call ESMF_AlarmDestroy (alarm1, rc=rc) - call ESMF_ClockDestroy (clock, rc=rc) - - ! ---------------------------------------------------------------------------- - !EX_UTest - !Test Alarm ringTime increment, first forwards a fixed number of - !timesteps, stopping at an alarm ringing time step. - !Using ESMF_DIRECTION_REVERSE, step backwards to some time prior to the - !clock's startTime. Then go ESMF_DIRECTION_FORWARD to one step past an - !alarm ringing time step, and then ESMF_DIRECTION_REVERSE once more. - ! Count number of rings. See bug #1531948. - write(failMsg, *) " Did not ring enough times during forward/backward march" - write(name, *) "Test ESMF_DIRECTION_FORWARD to an alarm point, " // & - "ESMF_DIRECTION_REVERSE, ESMF_DIRECTION_FORWARD, " // & - "ESMF_DIRECTION_REVERSE" - - testPass = .true. - call ESMF_TimeSet (startTime, yy=2008, mm=1, dd=23, h=0, & - calendar=gregorianCalendar, rc=rc) - !call ESMF_TimePrint (startTime, options="string isofrac", rc=rc) - call ESMF_TimeIntervalSet (timeStep, h=3, rc=rc) - clock = ESMF_ClockCreate(startTime = startTime, timeStep=timeStep, & - name="clock 1", rc=rc) - if (rc /= ESMF_SUCCESS) testPass = .false. - - call ESMF_TimeSet (alarmTime, yy=2008, mm=1, dd=23, h=6, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeIntervalSet (alarmStep, h=6, rc=rc) - alarm1 = ESMF_AlarmCreate ( & - name="Alarm 1", clock=clock, & - ringTime=alarmTime, ringInterval=alarmStep, rc=rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - - alarmCount = 0 - expectedCount = 11 - do, i=1,6 - call ESMF_ClockAdvance (clock, rc=rc) - !call ESMF_ClockPrint (clock, options="currTime string", rc=rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - if (ESMF_alarmIsRinging (alarm1)) then - alarmCount = alarmCount + 1 - !print *, 'alarm IS ringing at forwards timestep', i - call ESMF_AlarmRingerOff (alarm1, rc=rc) - else - !print *, 'alarm not ringing at forwards timestep', i - end if - end do - - !print *, 'SETTING CLOCK BACKWARDS' - call ESMF_ClockSet (clock, direction=ESMF_DIRECTION_REVERSE, rc=rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - - do, i=5, -5, -1 - call ESMF_ClockAdvance (clock, rc=rc) - !call ESMF_ClockPrint (clock, options="currTime string", rc=rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - if (ESMF_alarmIsRinging (alarm1)) then - alarmCount = alarmCount + 1 - !print *, 'alarm IS ringing at backwards timestep', i - call ESMF_AlarmRingerOff (alarm1, rc=rc) - !call ESMF_AlarmPrint(alarm1, options="ringTime string", rc=rc) - else - !print *, 'alarm not ringing at backwards timestep', i - !call ESMF_ClockPrint (clock, options="currTime string", rc=rc) - end if - end do - - !print *, 'SETTING CLOCK FORWARDS' - call ESMF_ClockSet (clock, direction=ESMF_DIRECTION_FORWARD, rc=rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - - do, i=-4,7 - call ESMF_ClockAdvance (clock, rc=rc) - !call ESMF_ClockPrint (clock, options="currTime string", rc=rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - if (ESMF_alarmIsRinging (alarm1)) then - alarmCount = alarmCount + 1 - !print *, 'alarm IS ringing at forwards timestep', i - call ESMF_AlarmRingerOff (alarm1, rc=rc) - else - !print *, 'alarm not ringing at forwards timestep', i - end if - end do - - !print *, 'SETTING CLOCK BACKWARDS' - call ESMF_ClockSet (clock, direction=ESMF_DIRECTION_REVERSE, rc=rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - - do, i=6, -5, -1 - call ESMF_ClockAdvance (clock, rc=rc) - !call ESMF_ClockPrint (clock, options="currTime string", rc=rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - if (ESMF_alarmIsRinging (alarm1)) then - alarmCount = alarmCount + 1 - !print *, 'alarm IS ringing at backwards timestep', i - call ESMF_AlarmRingerOff (alarm1, rc=rc) - !call ESMF_AlarmPrint(alarm1, options="ringTime string", rc=rc) - else - !print *, 'alarm not ringing at backwards timestep', i - !call ESMF_ClockPrint (clock, options="currTime string", rc=rc) - end if - end do - - if (.not. testPass .or. alarmCount /= expectedCount) then - if (.not. testPass) print *, 'bad return codes discovered' - write (failMsg,*) trim (failMsg), ', alarmCount = ', alarmCount, ', expected = ', expectedCount - print *, 'The alarm ringTime may be stuck at:' - call ESMF_AlarmPrint (alarm1, options="ringTime string", rc=rc) - end if - - call ESMF_Test (testPass .and. alarmCount == expectedCount, & - name, failMsg, result, ESMF_SRCLINE) - - call ESMF_AlarmDestroy (alarm1, rc=rc) - call ESMF_ClockDestroy (clock, rc=rc) - - ! ---------------------------------------------------------------------------- - - !EX_UTest - !Test Alarm ringTime increment, first forwards a fixed number of - !timesteps, stopping at an alarm ringing time step. Using a negative - !timestemp, step backwards to some time prior to the clock's startTime. - !Count number of rings. See bugs #1531948, #1457135. - write(failMsg, *) " Did not ring enough times during forward/backward march" - write(name, *) "Test forward to an alarm point, then step backward using a negative timeStep" - - testPass = .true. - call ESMF_TimeSet (startTime, yy=2008, mm=1, dd=23, h=0, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeIntervalSet (timeStep, h=3, rc=rc) - clock = ESMF_ClockCreate(startTime = startTime, timeStep=timeStep, & - name="clock 1", rc=rc) - if (rc /= ESMF_SUCCESS) testPass = .false. - - call ESMF_TimeSet (alarmTime, yy=2008, mm=1, dd=23, h=6, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeIntervalSet (alarmStep, h=6, rc=rc) - alarm1 = ESMF_AlarmCreate ( & - name="Alarm 1", clock=clock, & - ringTime=alarmTime, ringInterval=alarmStep, rc=rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - - alarmCount = 0 - expectedCount = 8 - do, i=1,6 - call ESMF_ClockAdvance (clock, rc=rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - if (ESMF_alarmIsRinging (alarm1)) then - alarmCount = alarmCount + 1 - !print *, 'alarm IS ringing at forwards timestep', i - call ESMF_AlarmRingerOff (alarm1, rc=rc) - else - !print *, 'alarm not ringing at forwards timestep', i - end if - end do - - !print *, 'SETTING CLOCK BACKWARDS WITH NEGATIVE TIMESTEP' - timeStep = -timeStep - call ESMF_ClockSet (clock, timeStep=timeStep, rc=rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - - do, i=5, -5, -1 - call ESMF_ClockAdvance (clock, rc=rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - if (ESMF_alarmIsRinging (alarm1)) then - alarmCount = alarmCount + 1 - !print *, 'alarm IS ringing at backwards timestep', i, ', time:' - !call ESMF_ClockPrint (clock, options="currTime string") - call ESMF_AlarmRingerOff (alarm1, rc=rc) - else - !print *, 'alarm not ringing at backwards timestep', i - !call ESMF_ClockPrint (clock, options="currTime string") - end if - end do - - if (.not. testPass .or. alarmCount /= expectedCount) then - if (.not. testPass) print *, 'bad return codes discovered' - write (failMsg,*) trim (failMsg), ', alarmCount = ', alarmCount, ', expected = ', expectedCount - print *, 'The alarm ringTime may be stuck at:' - call ESMF_AlarmPrint (alarm1, options="ringTime string", rc=rc) - end if - - call ESMF_Test (testPass .and. alarmCount == expectedCount, & - name, failMsg, result, ESMF_SRCLINE) - - call ESMF_AlarmDestroy (alarm1, rc=rc) - call ESMF_ClockDestroy (clock, rc=rc) - - ! ---------------------------------------------------------------------------- - - !EX_UTest - !Test Alarm ringTime increment, first forwards a fixed number of - !timesteps, stopping at a non-alarm ringing time step. Using a negative - !timestemp, step backwards to some time prior to the clock's startTime. - !Count number of rings. See bugs #1531948, #1457135. - write(failMsg, *) " Did not ring enough times during forward/backward march" - write(name, *) "Test forward to a non-ringing step, then step backward using a negative timeStep" - - testPass = .true. - call ESMF_TimeSet (startTime, yy=2008, mm=1, dd=23, h=0, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeIntervalSet (timeStep, h=3, rc=rc) - clock = ESMF_ClockCreate(startTime = startTime, timeStep=timeStep, & - name="clock 1", rc=rc) - if (rc /= ESMF_SUCCESS) testPass = .false. - - call ESMF_TimeSet (alarmTime, yy=2008, mm=1, dd=23, h=6, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeIntervalSet (alarmStep, h=6, rc=rc) - alarm1 = ESMF_AlarmCreate ( & - name="Alarm 1", clock=clock, & - ringTime=alarmTime, ringInterval=alarmStep, rc=rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - - alarmCount = 0 - expectedCount = 9 - do, i=1,7 - call ESMF_ClockAdvance (clock, rc=rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - if (ESMF_alarmIsRinging (alarm1)) then - alarmCount = alarmCount + 1 - !print *, 'alarm IS ringing at forwards timestep', i - call ESMF_AlarmRingerOff (alarm1, rc=rc) - else - !print *, 'alarm not ringing at forwards timestep', i - end if - end do - - !print *, 'SETTING CLOCK BACKWARDS WITH NEGATIVE TIMESTEP' - timeStep = -timeStep - call ESMF_ClockSet (clock, timeStep=timeStep, rc=rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - - do, i=6, -5, -1 - call ESMF_ClockAdvance (clock, rc=rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - if (ESMF_alarmIsRinging (alarm1)) then - alarmCount = alarmCount + 1 - !print *, 'alarm IS ringing at backwards timestep', i, ', time:' - !call ESMF_ClockPrint (clock, options="currTime string") - call ESMF_AlarmRingerOff (alarm1, rc=rc) - else - !print *, 'alarm not ringing at backwards timestep', i - !call ESMF_ClockPrint (clock, options="currTime string") - end if - end do - - if (.not. testPass .or. alarmCount /= expectedCount) then - if (.not. testPass) print *, 'bad return codes discovered' - write (failMsg,*) trim (failMsg), ', alarmCount = ', alarmCount, ', expected = ', expectedCount - print *, 'The alarm ringTime may be stuck at:' - call ESMF_AlarmPrint (alarm1, options="ringTime string", rc=rc) - end if - - call ESMF_Test (testPass .and. alarmCount == expectedCount, & - name, failMsg, result, ESMF_SRCLINE) - - ! - ! ---------------------------------------------------------------------------- - - !EX_UTest - write(failMsg, *) " Did not show null clock in alarm" - write(name, *) "Test alarm after destroying its associated clock" - call ESMF_ClockDestroy (clock, rc=rc) - willRingNext = ESMF_AlarmWillRingNext(alarm1, rc=rc) - call ESMF_Test (rc==ESMC_RC_PTR_NULL .and. .not.willRingNext, & - name, failMsg, result, ESMF_SRCLINE) - - call ESMF_AlarmDestroy (alarm1, rc=rc) - - ! ---------------------------------------------------------------------------- - - !EX_UTest - !Test Alarm ringTime increment, arbitrarily forwards and backwards using - ! positive and negative timesteps. Alarm ringTime and ringInterval are - ! changed with each change in timestep direction. The extent of the run - ! of each timestep value is different with each change in direction. - write(failMsg, *) " Did not ring enough times during arbitrary forward/backward march" - write(name, *) "Test arbitrary positive/negative timeStep runs with differing alarms" - - testPass = .true. - alarmCountPass = .true. - - call ESMF_TimeSet (startTime, yy=2008, mm=1, dd=23, h=0, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeIntervalSet (timeStep, h=1, rc=rc) - clock = ESMF_ClockCreate(startTime=startTime, timeStep=timeStep, & - name="clock 1", rc=rc) - if (rc /= ESMF_SUCCESS) testPass = .false. - - call ESMF_TimeSet (alarmTime, yy=2008, mm=1, dd=23, h=2, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeIntervalSet (alarmStep, h=2, rc=rc) - alarm1 = ESMF_AlarmCreate ( & - name="Alarm 1", clock=clock, & - ringTime=alarmTime, ringInterval=alarmStep, rc=rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - - alarmCount = 0 - expectedCount = 15 - - do, i=1,7 - call ESMF_ClockAdvance (clock, rc=rc) - !call ESMF_ClockPrint (clock, options="currTime string", rc=rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - if (ESMF_alarmIsRinging (alarm1)) then - alarmCount = alarmCount + 1 - !print *, 'alarm IS ringing at forwards timestep', i - call ESMF_AlarmRingerOff (alarm1, rc=rc) - else - !print *, 'alarm not ringing at forwards timestep', i - end if - end do - if (alarmCountPass .and. alarmCount /= 3) then - alarmCountPass = .false. - !print *, 'alarmCount = ', alarmCount, ' not 3 at 1st turnaround point' - end if - - !print *, 'SETTING CLOCK BACKWARDS WITH NEW NEGATIVE TIMESTEP AND RINGINTERVAL' - timeStep = -2 * timeStep - alarmStep = -2 * alarmStep - call ESMF_ClockSet (clock, timeStep=timeStep, rc=rc) - call ESMF_AlarmSet (alarm1, ringInterval=alarmStep, rc=rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - - do, i=6, -5, -1 - call ESMF_ClockAdvance (clock, rc=rc) - !call ESMF_ClockPrint (clock, options="currTime string", rc=rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - if (ESMF_alarmIsRinging (alarm1)) then - alarmCount = alarmCount + 1 - !print *, 'alarm IS ringing at backwards timestep', i - call ESMF_AlarmRingerOff (alarm1, rc=rc) - else - !print *, 'alarm not ringing at backwards timestep', i - end if - end do - if (alarmCountPass .and. alarmCount /= 9) then - alarmCountPass = .false. - !print *, 'alarmCount = ', alarmCount, ' not 9 at 2nd turnaround point' - end if - - !print *, 'SETTING CLOCK FORWARDS WITH NEW POSITIVE TIMESTEP, RINGINTERVAL, and RINGTIME' - call ESMF_TimeIntervalSet (timeStep, h=3, rc=rc) - call ESMF_TimeSet (alarmTime, yy=2008, mm=1, dd=22, h=11, & - calendar=gregorianCalendar, rc=rc) - call ESMF_TimeIntervalSet (alarmStep, h=6, rc=rc) - call ESMF_ClockSet (clock, timeStep=timeStep, rc=rc) - call ESMF_AlarmSet (alarm1, ringTime=alarmTime, ringInterval=alarmStep, & - rc=rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - - do, i=1,5 - call ESMF_ClockAdvance (clock, rc=rc) - !call ESMF_ClockPrint (clock, options="currTime string", rc=rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - if (ESMF_alarmIsRinging (alarm1)) then - alarmCount = alarmCount + 1 - !print *, 'alarm IS ringing at forwards timestep', i - call ESMF_AlarmRingerOff (alarm1, rc=rc) - else - !print *, 'alarm not ringing at forwards timestep', i - end if - end do - if (alarmCountPass .and. alarmCount /= 11) then - alarmCountPass = .false. - !print *, 'alarmCount = ', alarmCount, ' not 11 at 3rd turnaround point' - end if - - !print *, 'SETTING CLOCK BACKWARDS WITH NEW NEGATIVE TIMESTEP AND RINGTIME' - call ESMF_TimeIntervalSet (timeStep, h=-1, rc=rc) - call ESMF_TimeSet (alarmTime, yy=2008, mm=1, dd=22, h=21, & - calendar=gregorianCalendar, rc=rc) - call ESMF_ClockSet (clock, timeStep=timeStep, rc=rc) - call ESMF_AlarmSet (alarm1, ringTime=alarmTime, rc=rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - - do, i=4,2,-1 - call ESMF_ClockAdvance (clock, rc=rc) - !call ESMF_ClockPrint (clock, options="currTime string", rc=rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - if (ESMF_alarmIsRinging (alarm1)) then - alarmCount = alarmCount + 1 - !print *, 'alarm IS ringing at backwards timestep', i - call ESMF_AlarmRingerOff (alarm1, rc=rc) - else - !print *, 'alarm not ringing at backwards timestep', i - end if - end do - if (alarmCountPass .and. alarmCount /= 12) then - alarmCountPass = .false. - !print *, 'alarmCount = ', alarmCount, ' not 12 at 4th turnaround point' - end if - - !print *, 'SETTING CLOCK FORWARDS WITH NEW POSITIVE TIMESTEP' - timeStep = -timeStep - call ESMF_ClockGet(clock, currTime=startTime, rc=rc) - call ESMF_ClockSet(clock, timeStep=timeStep, startTime=startTime, & - runTimeStepCount=15, rc=rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - - do while (.not. ESMF_ClockIsDone(clock, rc=rc)) - call ESMF_ClockAdvance (clock, rc=rc) - !call ESMF_ClockPrint (clock, options="currTime string", rc=rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - if (ESMF_alarmIsRinging (alarm1)) then - alarmCount = alarmCount + 1 - !print *, 'alarm IS ringing' - call ESMF_AlarmRingerOff (alarm1, rc=rc) - else - !print *, 'alarm not ringing' - end if - end do - if (alarmCountPass .and. alarmCount /= expectedCount) then - alarmCountPass = .false. - !print *, 'alarmCount = ', alarmCount, ', not ', expectedCount, ' at the end' - end if - - if (.not. alarmCountPass) then - write(failMsg,*) trim(failMsg), ', alarmCount incorrect at one or more turnaround points' - !print *, 'Final alarmCount = ', alarmCount, ', expected = ', expectedCount - !print *, 'Final alarm ringTime:' - !call ESMF_AlarmPrint (alarm1, "ringTime string", rc=rc) - end if - - if (.not. testPass) print *, 'bad return codes discovered' - - call ESMF_Test (testPass .and. alarmCountPass, & - name, failMsg, result, ESMF_SRCLINE) - - call ESMF_AlarmDestroy (alarm1, rc=rc) - call ESMF_ClockDestroy (clock, rc=rc) - - ! ---------------------------------------------------------------------------- -#if 1 - ! The following tests are from Ben@NASA's support ticket 3614994 - write(failMsg, *) " Alarms did not rewind correct number of times " - write(name, *) "Test multiple alarms rewind correct number of times " - rc = ESMF_SUCCESS - testPass = .true. - call Test_ReverseAlarms(testPass, rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - if (.not. testPass) print *, 'bad return codes discovered' - call ESMF_Test (testPass, name, failMsg, result, ESMF_SRCLINE) - - ! ---------------------------------------------------------------------------- - - write(failMsg, *) " Alarms hang... " - write(name, *) "Test multiple alarms replay without hanging " - rc = ESMF_SUCCESS - testPass = .true. - call Test_AlarmHang(testPass, rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - if (.not. testPass) print *, 'bad return codes discovered' - call ESMF_Test (testPass, name, failMsg, result, ESMF_SRCLINE) - - ! ---------------------------------------------------------------------------- - - write(failMsg, *) " Alarms with ring intervals equal to clock interval, incorrect behavior " - write(name, *) "Test running an alarms forward-reverse-forward with ring interval equal to clock interval " - rc = ESMF_SUCCESS - testPass = .true. - call Test_AlarmAdvRewind(testPass, rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - if (.not. testPass) print *, 'bad return codes discovered' - call ESMF_Test (testPass, name, failMsg, result, ESMF_SRCLINE) - - ! ---------------------------------------------------------------------------- - - write(failMsg, *) " Alarms reverse with sticky set... " - write(name, *) "Test running an alarm reverse with sticky bit set " - rc = ESMF_SUCCESS - testPass = .true. - call Test_RevAlarmSticky(60._ESMF_KIND_R8, testPass, rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - if (.not. testPass) print *, 'bad return codes discovered' - call ESMF_Test (testPass, name, failMsg, result, ESMF_SRCLINE) - - ! ---------------------------------------------------------------------------- - - write(failMsg, *) " Alarms with ClockSet... " - write(name, *) "Test ClockSet after alarm attached to clock " - rc = ESMF_SUCCESS - testPass = .true. - call Test_ClockSet(testPass, rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - if (.not. testPass) print *, 'bad return codes discovered' - call ESMF_Test (testPass, name, failMsg, result, ESMF_SRCLINE) - ! ---------------------------------------------------------------------------- - - write(failMsg, *) " Alarms with getPrevRingTime... " - write(name, *) "Test getPrevRingTime... after alarm attached to clock " - rc = ESMF_SUCCESS - testPass = .true. - call Test_GetPrevRingTime(testPass, rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - if (.not. testPass) print *, 'bad return codes discovered' - call ESMF_Test (testPass, name, failMsg, result, ESMF_SRCLINE) -#endif - - ! ---------------------------------------------------------------------------- -#endif - - ! destroy calendars - call ESMF_CalendarDestroy(esmf_360dayCalendar, rc=rc) - call ESMF_CalendarDestroy(no_leapCalendar, rc=rc) - call ESMF_CalendarDestroy(julianCalendar, rc=rc) - call ESMF_CalendarDestroy(gregorianCalendar, rc=rc) - - ! finalize ESMF framework - call ESMF_TestEnd(ESMF_SRCLINE) - -#if 1 - contains - - subroutine test_reverseAlarms(testPass, rc) - implicit none - - logical, intent(out) :: testPass - integer :: status,rc - - type(ESMF_TimeInterval) :: dt - type(ESMF_Time) :: start_time, clock_start, clock_end - type(ESMF_Clock) :: clock - character(len=5) :: add_2nd - integer :: nargs - - type(ESMF_TimeInterval) :: tint - type(ESMF_Alarm) :: esmfalarm, firstalarm - - integer :: i,nstep, nrings1, nrings2 - - type(ESMF_Time) :: time - character(len=10) :: iam='test_clock' - logical :: esmf_ring - integer :: nalarms, n_rings=0 - - testPass = .false. - call ESMF_CalendarSetDefault ( ESMF_CALKIND_GREGORIAN, rc=status ) - call verify_(status) - call ESMF_TimeSet(clock_start,yy=2000,mm=1,dd=1,h=21,m=0,s=0,rc=status) - call verify_(status) - call ESMF_TimeSet(clock_end,yy=2000,mm=12,dd=1,h=21,m=0,s=0,rc=status) - call verify_(status) - call ESMF_TimeSet(start_time,yy=2000,mm=10,dd=1,h=21,m=0,s=0,rc=status) - call verify_(status) - call ESMF_TimeIntervalSet(dt,S=900, sN=0, sD=1,rc=status) - call verify_(status) - clock= ESMF_ClockCreate(timeStep=dt,startTime=clock_start,stopTime=clock_end,rc=status) - call verify_(status) - call ESMF_ClockSet(clock,currTime=start_time,rc=status) - call verify_(status) - - call ESMF_ClockGet(clock,currtime=start_time,rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() - call ESMF_TimeIntervalSet(tint,h=2,rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() - firstalarm = ESMF_AlarmCreate(clock=clock,ringInterval=tint,ringTime=start_time,sticky=.false.,name="alarm1",rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_ClockGet(clock,currtime=start_time,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeIntervalSet(tint,h=2,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + firstalarm = ESMF_AlarmCreate(clock=clock,ringInterval=tint,ringTime=start_time,sticky=.false.,name="alarm1",rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() nstep=47 call ESMF_ClockGet(clock,currtime=start_time,alarmCount=nalarms,rc=status) @@ -3488,6 +1320,10 @@ subroutine test_reverseAlarms(testPass, rc) nrings1 = 0 nrings2 = 0 do i=1,nstep + !call ESMF_ClockDebug(clock, 'forward clock', rc=status) + !call verify_(status) + !call ESMF_AlarmDebug(esmfalarm, 'forward esmfalarm', rc=status) + !call verify_(status) call ESMF_ClockGet(clock,currTime=time) esmf_ring = ESMF_AlarmIsRinging(esmfalarm,rc=status) call verify_(status) @@ -3498,6 +1334,12 @@ subroutine test_reverseAlarms(testPass, rc) end if call ESMF_ClockAdvance(clock) enddo + if(nrings2 == 12) then + testPass = .true. ! ringerIV = 1h, timeST=15min, 48/4=12 + else + return + endif + testPass = .false. call ESMF_ClockSet(clock, direction=ESMF_DIRECTION_REVERSE, rc=status) call verify_(status) !write(*,*)"*************** start rewind *********************" @@ -3507,6 +1349,10 @@ subroutine test_reverseAlarms(testPass, rc) write(*,*) 'Rewind step: ', i call ESMF_ClockAdvance(clock,rc=status) call verify_(status) + !call ESMF_ClockDebug(clock, 'reverse clock', rc=status) + !call verify_(status) + !call ESMF_AlarmDebug(esmfalarm, 'reverse esmfalarm', rc=status) + !call verify_(status) call ESMF_ClockGet(clock,currTime=time) if (ESMF_AlarmIsRinging(esmfalarm)) then write(*,*)'rewinding one step ',ESMF_AlarmIsRinging(esmfalarm) @@ -3516,10 +1362,20 @@ subroutine test_reverseAlarms(testPass, rc) if (time == start_time) exit enddo + if(n_rings == 12) then + testPass = .true. ! ringerIV = 1h, timeST=15min, 48/4=12 + else + return + endif + testPass = .false. call ESMF_ClockSet(clock, direction=ESMF_DIRECTION_FORWARD, rc=status) call verify_(status) write(*,*)"*************** end rewind *********************" do i=1,nstep*2 + !call ESMF_ClockDebug(clock, 'forward clock again', rc=status) + !call verify_(status) + !call ESMF_AlarmDebug(esmfalarm, 'forward esmfalarm again', rc=status) + !call verify_(status) call ESMF_ClockGet(clock,currTime=time) esmf_ring = ESMF_AlarmIsRinging(esmfalarm,rc=status) call verify_(status) @@ -3805,10 +1661,10 @@ subroutine Test_RevAlarmSticky(dt, testPass, rc) #if 1 alarm = ESMF_AlarmCreate(clock, ringTime=ring_time, sticky=sticky_alarm, & - ringTimeStepCount=1, rc=rc) ; CHECKRC + rc=rc) ; CHECKRC #else alarm = ESMF_AlarmCreate(clock, ringTime=ring_time, sticky=.false., & - ringTimeStepCount=1, rc=rc) ; CHECKRC + rc=rc) ; CHECKRC #endif call ESMF_alarmPrint(alarm,options='sticky') @@ -3843,53 +1699,71 @@ subroutine Test_ClockSet(testPass, rc) logical :: reverse_clock, sticky_alarm rc = ESMF_SUCCESS + + call ESMF_CalendarSetDefault ( ESMF_CALKIND_GREGORIAN, rc=rc) + CHECKRC - call ESMF_TimeSet(time, yy=2021, mm=4, dd=6, rc=rc) ; CHECKRC - + call ESMF_TimeSet(time, yy=2021, mm=4, dd=6, rc=rc) + CHECKRC secs = 0 - call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) ; CHECKRC + call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) + CHECKRC + initial = time + esmf_ival - call ESMF_TimePrint(initial, options="string", rc=rc) ; CHECKRC + call ESMF_TimePrint(initial, options="string", rc=rc) + CHECKRC secs = 6000 - call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) ; CHECKRC - finish = time + esmf_ival - call ESMF_TimePrint(finish, options="string", rc=rc) ; CHECKRC + call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) + CHECKRC + finish = time + 2*esmf_ival + call ESMF_TimePrint(finish, options="string", rc=rc) + CHECKRC secs = 60 - call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) ; CHECKRC + call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) + CHECKRC clock = ESMF_Clockcreate(timeStep=esmf_ival & ,startTime=initial,stopTime=finish & - ,refTime=time, rc=rc ) ; CHECKRC + ,refTime=time, rc=rc ) + CHECKRC - call ESMF_ClockSet(clock,direction=ESMF_DIRECTION_REVERSE, rc=rc) ; CHECKRC + call ESMF_ClockSet(clock,direction=ESMF_DIRECTION_REVERSE, rc=rc) + CHECKRC - reverse_clock = ESMF_ClockIsReverse(clock, rc=rc) ; CHECKRC + reverse_clock = ESMF_ClockIsReverse(clock, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) sticky_alarm = .not.reverse_clock write(0,'("reverse =",x,l)') reverse_clock write(0,'("sticky =",x,l)') sticky_alarm secs = 3000 - call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) ; CHECKRC - ring_time = initial + esmf_ival + call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) + CHECKRC + ring_time = initial + 2*esmf_ival print *, 'Before Alarm Create ringTime: ' - call ESMF_TimePrint(ring_time, options="string", rc=rc) ; CHECKRC + call ESMF_TimePrint(ring_time, options="string", rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) #if 1 alarm = ESMF_AlarmCreate(clock, ringTime=ring_time, sticky=sticky_alarm, & - ringTimeStepCount=1, rc=rc) ; CHECKRC + rc=rc) + CHECKRC #else alarm = ESMF_AlarmCreate(clock, ringTime=ring_time, sticky=.false., & - ringTimeStepCount=1, rc=rc) ; CHECKRC + rc=rc) + CHECKRC #endif - call ESMF_TimePrint(ring_time, options="string", rc=rc) ; CHECKRC - call ESMF_AlarmGet(alarm, ringTime=ring_time, rc=rc) ; CHECKRC + call ESMF_TimePrint(ring_time, options="string", rc=rc) + CHECKRC print *, 'After Alarm Create ringTime: ' - call ESMF_TimePrint(ring_time, options="string", rc=rc) ; CHECKRC + call ESMF_TimePrint(ring_time, options="string", rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) - call ESMF_ClockSet(clock, stopTime=ring_time, rc=rc) ; CHECKRC + call ESMF_ClockSet(clock, stopTime=ring_time, rc=rc) + CHECKRC call ESMF_alarmPrint(alarm,options='sticky') @@ -3924,24 +1798,25 @@ subroutine Test_GetPrevRingTime(testPass, rc) initial = time + esmf_ival call ESMF_TimePrint(initial, options="string", rc=rc) ; CHECKRC - secs = 6000 + secs = 6000 ! 100 minutes call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) ; CHECKRC finish = time + esmf_ival call ESMF_TimePrint(finish, options="string", rc=rc) ; CHECKRC - secs = 60 + secs = 60 ! 1 minute call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) ; CHECKRC clock = ESMF_Clockcreate(timeStep=esmf_ival & ,startTime=initial,stopTime=finish & ,refTime=time, rc=rc ) ; CHECKRC - secs = 120 ! alarm step is clock step x 2 + secs = 120 ! alarm step is clock step x 2, 2 minutes call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) ; CHECKRC ring_time = initial alarm = ESMF_AlarmCreate(clock, ringTime=ring_time, ringInterval=esmf_ival, & - rc=rc) ; CHECKRC + sticky=.false., rc=rc) ; CHECKRC nrings = 0 + prevTime = initial do i=1,nstep call ESMF_ClockAdvance(clock) call ESMF_ClockGet(clock,currTime=time) @@ -3949,17 +1824,16 @@ subroutine Test_GetPrevRingTime(testPass, rc) call verify_(rc) if ( esmf_ring) then nrings = nrings + 1 - write(*,*) 'alarm is ringing' + write(*,*) 'alarm is ringing', nrings call ESMF_TimePrint(time,options='string') - call ESMF_AlarmGet(alarm, ringTime=ringTime, prevRingTime=prevTime, rc=rc) + call ESMF_AlarmGet(alarm, ringTime=ringTime, rc=rc) call verify_(rc) - write(*,*) 'prev Ring Time' - call ESMF_TimePrint(prevTime,options='string') write(*,*) 'Ring Time' call ESMF_TimePrint(ringTime,options='string') diffTime = ringTime - prevTime if(diffTime /= esmf_ival) testPass = .false. ! both should be 20 minutes or 120 seconds + prevTime = ringTime end if enddo @@ -3994,4 +1868,844 @@ end subroutine Test_GetPrevRingTime #endif + character*64 function clockCurrTime(clock) + type(ESMF_Clock) :: clock + type(ESMF_Time ) :: time + integer :: yy, mm, dd, d, h, m, s, rc + type (ESMF_VM) :: vm + integer :: lpet + + call ESMF_ClockGet(clock, currTime=time, rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize() + + call ESMF_TimeGet(Time, yy=yy, mm=mm, dd=dd, d=d, h=h, m=m, s=s, rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize() + + call ESMF_VMGetCurrent(vm=vm, rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize() + + call ESMF_VMGet(vm, localpet = lpet, rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize() + + if(lpet == 0) then + !write(clockCurrTime, '(3I4, 3I4)') yy, mm, dd, h, m, s + write(clockCurrTime, '(I2.2,A1,I2.2,A1,I2.2)') h, ':', m, ':', s + endif + end function + +!------------------------------------------------------------------------ +! Forward Tests +!------------------------------------------------------------------------ + subroutine ForwardAlarm_Test1(rc) + + integer, intent(out) :: rc + + type (ESMF_Clock) :: clock + type (ESMF_Alarm) :: alarm + type (ESMF_Time) :: startTime, stopTime, ringTime + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + + integer :: status, n, nrings=0 + logical :: ringing, enabled, sticky + + call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + ! Test 1: c.t0 = a.t0, c.dt = a.dt = 10 min + print *, 'Test 1: c.t0 = a.t0, c.dt = a.dt = 10 min' + call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeIntervalSet(ringTimeInterval,S=600, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + clock = ESMF_ClockCreate(timeStep=timeStep,startTime=startTime,stopTime=stopTime,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, ringInterval=ringTimeInterval, enabled=.true., sticky=.false., name='alarm', rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + !call ESMF_AlarmDebug(alarm,'test1',rc=status) + !if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + print *, 'Test 1: ringing = ', ringing, trim(clockCurrTime(clock)) + if(ringing) nrings = nrings + 1 + do n = 1, 6 + call ESMF_ClockAdvance(clock,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + if(ringing) nrings = nrings + 1 + print *, ' Test 1: ringing = ', ringing, trim(clockCurrTime(clock)) + enddo + + rc = ESMF_FAILURE + if(nrings == 7) rc = ESMF_SUCCESS + end subroutine +!------------------------------------------------------------------------ + subroutine ForwardAlarm_Test2(rc) + + integer, intent(out) :: rc + + type (ESMF_Clock) :: clock + type (ESMF_Alarm) :: alarm + type (ESMF_Time) :: startTime, stopTime, ringTime + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + + integer :: status, n, nrings=0 + logical :: ringing, enabled, sticky + + call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + print *, 'Test 2: c.t0 = a.t0, c.dt = 10 min a.dt = 20 min' + call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeIntervalSet(ringTimeInterval,S=1200, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + clock = ESMF_ClockCreate(timeStep=timeStep,startTime=startTime,stopTime=stopTime,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, ringInterval=ringTimeInterval, enabled=.true., sticky=.false., name='alarm', rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + !call ESMF_AlarmDebug(alarm,'test2',rc=status) + !if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + print *, 'Test 2: ringing = ', ringing, trim(clockCurrTime(clock)) + if(ringing) nrings = nrings + 1 + do n = 1, 6 + call ESMF_ClockAdvance(clock,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + print *, ' Test 2: ringing = ', ringing, trim(clockCurrTime(clock)) + if(ringing) nrings = nrings + 1 + enddo + + rc = ESMF_FAILURE + if(nrings == 4) rc = ESMF_SUCCESS + end subroutine +!------------------------------------------------------------------------ + subroutine ForwardAlarm_Test3(rc) + + integer, intent(out) :: rc + + type (ESMF_Clock) :: clock + type (ESMF_Alarm) :: alarm + type (ESMF_Time) :: startTime, stopTime, ringTime + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + + integer :: status, n, nrings=0 + logical :: ringing, enabled, sticky + + rc = ESMF_SUCCESS + !print *, 'Test 3: c.t0 = a.t0, c.dt = 20 min a.dt = 10 min' + call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + call ESMF_TimeIntervalSet(timeStep,S=1200, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeIntervalSet(ringTimeInterval,S=600, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + clock = ESMF_ClockCreate(timeStep=timeStep,startTime=startTime,stopTime=stopTime,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + ! It's an error to create an alarm with alarm timeInterval less than clock timeStep + alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, ringInterval=ringTimeInterval, enabled=.true., sticky=.false., name='alarm', rc=status) + if(status /= ESMF_SUCCESS) return + call ESMF_AlarmDebug(alarm,'test3',rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + print *, 'Test 3: ringing = ', ringing, trim(clockCurrTime(clock)) + do n = 1, 6 + call ESMF_ClockAdvance(clock,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + print *, ' Test 3: ringing = ', ringing, trim(clockCurrTime(clock)) + enddo + + rc = ESMF_FAILURE + end subroutine +!------------------------------------------------------------------------ + subroutine ForwardAlarm_Test4(rc) + + integer, intent(out) :: rc + + type (ESMF_Clock) :: clock + type (ESMF_Alarm) :: alarm + type (ESMF_Time) :: startTime, stopTime, ringTime + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + + integer :: status, n, nrings=0 + logical :: ringing, enabled, sticky + + rc = ESMF_SUCCESS + + call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + ! Test 4: c.t0 = a.t0, c.dt = 10 min a.dt = 12 min + print *, 'Test 4: c.t0 = a.t0, c.dt = 10 min a.dt = 12 min' + call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeIntervalSet(ringTimeInterval,S=720, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeIntervalSet(ringDuration,S=1, sN=0, sD=1,rc=status) + + clock = ESMF_ClockCreate(timeStep=timeStep,startTime=startTime,stopTime=stopTime,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, ringInterval=ringTimeInterval, enabled=.true., sticky=.false., name='alarm', rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_AlarmDebug(alarm,'test4',rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + write(*, '(A20,Z16)') 'LOC(sticky) = ', LOC(sticky) + + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + if(ringing) nrings = nrings + 1 + print *, 'Test 4: ringing = ', ringing, trim(clockCurrTime(clock)), ' sticky = ', sticky + do n = 1, 6 + call ESMF_ClockAdvance(clock,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + if(ringing) nrings = nrings + 1 + print *, ' Test 4: ringing = ', ringing, trim(clockCurrTime(clock)) + enddo + + rc = ESMF_FAILURE + if(nrings == 2) rc = ESMF_SUCCESS + end subroutine +!------------------------------------------------------------------------ + subroutine ForwardAlarm_Test5(rc) + + integer, intent(out) :: rc + + type (ESMF_Clock) :: clock + type (ESMF_Alarm) :: alarm + type (ESMF_Time) :: startTime, stopTime, ringTime + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + + integer :: status, n, nrings=0 + logical :: ringing, enabled, sticky + + rc = ESMF_SUCCESS + + call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + print *, 'Test 5: c.t0 = 0:0:0 a.t0=0:4:0, c.dt = a.dt = 10 min sticky (an alarm wont ring)' + call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeIntervalSet(ringTimeInterval,S=600, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + clock = ESMF_ClockCreate(timeStep=timeStep,startTime=startTime,stopTime=stopTime,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=4,s=0,rc=status) + alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, ringInterval=ringTimeInterval, enabled=.true., sticky=.true., name='alarm', rc=status) + if(status /= ESMF_SUCCESS) return + call ESMF_AlarmDebug(alarm,'test5',rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + print *, 'Test 5: ringing = ', ringing, trim(clockCurrTime(clock)) + do n = 1, 6 + call ESMF_ClockAdvance(clock,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + print *, ' Test 5: ringing = ', ringing, trim(clockCurrTime(clock)) + enddo + + end subroutine +!------------------------------------------------------------------------ + subroutine ForwardAlarm_Test6(rc) + + integer, intent(out) :: rc + + type (ESMF_Clock) :: clock + type (ESMF_Alarm) :: alarm + type (ESMF_Time) :: startTime, stopTime, ringTime + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + + integer :: status, n, nrings=0 + logical :: ringing, enabled, sticky + + rc = ESMF_SUCCESS + + call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=30,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + ! Test 6: c.t0 = a.t0, c.dt = 10 min a.dt = 12 min + print *, 'Test 6: c.t0 = a.t0, c.dt = 10 min a.dt = unspecified (one shot)' + call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeIntervalSet(ringTimeInterval,S=720, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeIntervalSet(ringDuration,S=1, sN=0, sD=1,rc=status) + + clock = ESMF_ClockCreate(timeStep=timeStep,startTime=startTime,stopTime=stopTime,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, enabled=.true., sticky=.false., name='alarm', rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_AlarmDebug(alarm,'test6',rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + if(ringing) nrings = nrings + 1 + print *, 'Test 6: ringing = ', ringing, trim(clockCurrTime(clock)), ' sticky = ', sticky + do n = 1, 6 + call ESMF_ClockAdvance(clock,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + if(ringing) nrings = nrings + 1 + print *, ' Test 6: ringing = ', ringing, trim(clockCurrTime(clock)) + enddo + + rc = ESMF_FAILURE + if(nrings == 1) rc = ESMF_SUCCESS + end subroutine + +!------------------------------------------------------------------------ +! Reverse Tests +!------------------------------------------------------------------------ + subroutine ReverseAlarm_Test1(rc) + + integer, intent(out) :: rc + + type (ESMF_Clock) :: clock + type (ESMF_Alarm) :: alarm + type (ESMF_Time) :: startTime, stopTime, ringTime, currTime + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + + integer :: status, n, nrings=0 + logical :: ringing, enabled, sticky + + call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + ! Test 1: c.t0 = a.t0, c.dt = a.dt = -10 min + print *, 'Test 1: c.t0 = a.t0, c.dt = a.dt = 10 min' + call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeIntervalSet(ringTimeInterval,S=600, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + clock = ESMF_ClockCreate(timeStep=timeStep,startTime=startTime,stopTime=stopTime,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_ClockSet(clock, currTime = stopTime, direction=ESMF_DIRECTION_REVERSE, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, ringInterval=ringTimeInterval, enabled=.true., sticky=.false., name='alarm', rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + !call ESMF_AlarmDebug(alarm,'test1',rc=status) + !if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + print *, 'Test 1: ringing = ', ringing, trim(clockCurrTime(clock)) + if(ringing) nrings = nrings + 1 + do n = 1, 6 + call ESMF_ClockAdvance(clock,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + if(ringing) nrings = nrings + 1 + print *, ' Test 1: ringing = ', ringing, trim(clockCurrTime(clock)) + enddo + + rc = ESMF_FAILURE + if(nrings == 7) rc = ESMF_SUCCESS + end subroutine +!------------------------------------------------------------------------ + subroutine ReverseAlarm_Test2(rc) + + integer, intent(out) :: rc + + type (ESMF_Clock) :: clock + type (ESMF_Alarm) :: alarm + type (ESMF_Time) :: startTime, stopTime, ringTime + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + + integer :: status, n, nrings=0 + logical :: ringing, enabled, sticky + + call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + print *, 'Test 2: c.t0 = a.t0, c.dt = 10 min a.dt = 20 min' + call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeIntervalSet(ringTimeInterval,S=1200, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + clock = ESMF_ClockCreate(timeStep=timeStep,startTime=startTime,stopTime=stopTime,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_ClockSet(clock, currTime = stopTime, direction=ESMF_DIRECTION_REVERSE, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, ringInterval=ringTimeInterval, enabled=.true., sticky=.false., name='alarm', rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + !call ESMF_AlarmDebug(alarm,'test2',rc=status) + !if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + print *, 'Test 2: ringing = ', ringing, trim(clockCurrTime(clock)) + if(ringing) nrings = nrings + 1 + do n = 1, 6 + call ESMF_ClockAdvance(clock,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + print *, ' Test 2: ringing = ', ringing, trim(clockCurrTime(clock)) + if(ringing) nrings = nrings + 1 + enddo + + rc = ESMF_FAILURE + if(nrings == 4) rc = ESMF_SUCCESS + end subroutine +!------------------------------------------------------------------------ + subroutine ReverseAlarm_Test3(rc) + + integer, intent(out) :: rc + + type (ESMF_Clock) :: clock + type (ESMF_Alarm) :: alarm + type (ESMF_Time) :: startTime, stopTime, ringTime + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + + integer :: status, n, nrings=0 + logical :: ringing, enabled, sticky + + rc = ESMF_SUCCESS + !print *, 'Test 3: c.t0 = a.t0, c.dt = 20 min a.dt = 10 min' + call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + call ESMF_TimeIntervalSet(timeStep,S=1200, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeIntervalSet(ringTimeInterval,S=600, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + clock = ESMF_ClockCreate(timeStep=timeStep,startTime=startTime,stopTime=stopTime,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_ClockSet(clock, currTime = stopTime, direction=ESMF_DIRECTION_REVERSE, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + ! It's an error to create an alarm with alarm timeInterval less than clock timeStep + alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, ringInterval=ringTimeInterval, enabled=.true., sticky=.false., name='alarm', rc=status) + if(status /= ESMF_SUCCESS) return + call ESMF_AlarmDebug(alarm,'test3',rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + print *, 'Test 3: ringing = ', ringing, trim(clockCurrTime(clock)) + do n = 1, 6 + call ESMF_ClockAdvance(clock,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + print *, ' Test 3: ringing = ', ringing, trim(clockCurrTime(clock)) + enddo + + rc = ESMF_FAILURE + end subroutine +!------------------------------------------------------------------------ + subroutine ReverseAlarm_Test4(rc) + + integer, intent(out) :: rc + + type (ESMF_Clock) :: clock + type (ESMF_Alarm) :: alarm + type (ESMF_Time) :: startTime, stopTime, ringTime + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + + integer :: status, n, nrings=0 + logical :: ringing, enabled, sticky + + rc = ESMF_SUCCESS + + call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + ! Test 4: c.t0 = a.t0, c.dt = 10 min a.dt = 12 min + print *, 'Test 4: c.t0 = a.t0, c.dt = 10 min a.dt = 12 min' + call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeIntervalSet(ringTimeInterval,S=720, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeIntervalSet(ringDuration,S=1, sN=0, sD=1,rc=status) + + clock = ESMF_ClockCreate(timeStep=timeStep,startTime=startTime,stopTime=stopTime,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_ClockSet(clock, currTime = stopTime, direction=ESMF_DIRECTION_REVERSE, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, ringInterval=ringTimeInterval, enabled=.true., sticky=.false., name='alarm', rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_AlarmDebug(alarm,'test4',rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + write(*, '(A20,Z16)') 'LOC(sticky) = ', LOC(sticky) + + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + if(ringing) nrings = nrings + 1 + print *, 'Test 4: ringing = ', ringing, trim(clockCurrTime(clock)), ' sticky = ', sticky + do n = 1, 6 + call ESMF_ClockAdvance(clock,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + if(ringing) nrings = nrings + 1 + print *, ' Test 4: ringing = ', ringing, trim(clockCurrTime(clock)) + enddo + + rc = ESMF_FAILURE + if(nrings == 2) rc = ESMF_SUCCESS + end subroutine +!------------------------------------------------------------------------ + subroutine ReverseAlarm_Test5(rc) + + integer, intent(out) :: rc + + type (ESMF_Clock) :: clock + type (ESMF_Alarm) :: alarm + type (ESMF_Time) :: startTime, stopTime, ringTime + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + + integer :: status, n, nrings=0 + logical :: ringing, enabled, sticky + + rc = ESMF_SUCCESS + + call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + print *, 'Test 5: c.t0 = 0:0:0 a.t0=0:4:0, c.dt = a.dt = 10 min sticky (an alarm wont ring)' + call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeIntervalSet(ringTimeInterval,S=600, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + clock = ESMF_ClockCreate(timeStep=timeStep,startTime=startTime,stopTime=stopTime,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_ClockSet(clock, currTime = stopTime, direction=ESMF_DIRECTION_REVERSE, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=4,s=0,rc=status) + alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, ringInterval=ringTimeInterval, enabled=.true., sticky=.true., name='alarm', rc=status) + if(status /= ESMF_SUCCESS) return + call ESMF_AlarmDebug(alarm,'test5',rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + print *, 'Test 5: ringing = ', ringing, trim(clockCurrTime(clock)) + do n = 1, 6 + call ESMF_ClockAdvance(clock,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + print *, ' Test 5: ringing = ', ringing, trim(clockCurrTime(clock)) + enddo + + end subroutine +!------------------------------------------------------------------------ + subroutine ReverseAlarm_Test6(rc) + + integer, intent(out) :: rc + + type (ESMF_Clock) :: clock + type (ESMF_Alarm) :: alarm + type (ESMF_Time) :: startTime, stopTime, ringTime + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + + integer :: status, n, nrings=0 + logical :: ringing, enabled, sticky + + rc = ESMF_SUCCESS + + call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=30,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + ! Test 6: c.t0 = a.t0, c.dt = 10 min a.dt = 12 min + print *, 'Test 6: c.t0 = a.t0, c.dt = 10 min a.dt = unspecified (one shot)' + call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeIntervalSet(ringTimeInterval,S=720, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeIntervalSet(ringDuration,S=1, sN=0, sD=1,rc=status) + + clock = ESMF_ClockCreate(timeStep=timeStep,startTime=startTime,stopTime=stopTime,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_ClockSet(clock, currTime = stopTime, direction=ESMF_DIRECTION_REVERSE, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, enabled=.true., sticky=.false., name='alarm', rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_AlarmDebug(alarm,'test6',rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + if(ringing) nrings = nrings + 1 + print *, 'Test 6: ringing = ', ringing, trim(clockCurrTime(clock)), ' sticky = ', sticky + do n = 1, 6 + call ESMF_ClockAdvance(clock,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + if(ringing) nrings = nrings + 1 + print *, ' Test 6: ringing = ', ringing, trim(clockCurrTime(clock)) + enddo + + rc = ESMF_FAILURE + if(nrings == 1) rc = ESMF_SUCCESS + end subroutine + +!------------------------------------------------------------------------ +! Forward and Reverse +!------------------------------------------------------------------------ + subroutine ForwardReverseAlarm_Test1(rc) + + integer, intent(out) :: rc + + type (ESMF_Clock) :: clock + type (ESMF_Alarm) :: alarm + type (ESMF_Time) :: startTime, stopTime, ringTime + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + + integer :: status, n, nrings=0 + logical :: ringing, enabled, sticky + + rc = ESMF_SUCCESS + print *, 'Forward and Reverse Alarms Tests: ' + call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + ! Test 1: c.t0 = a.t0, c.dt = a.dt = 10 min + print *, 'Test 1: c.t0 = a.t0, c.dt = a.dt = 10 min' + call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeIntervalSet(ringTimeInterval,S=600, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + clock = ESMF_ClockCreate(timeStep=timeStep,startTime=startTime,stopTime=stopTime,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, ringInterval=ringTimeInterval, enabled=.true., sticky=.false., name='alarm', rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_AlarmDebug(alarm,'test1',rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + if(ringing) nrings = nrings + 1 + print *, 'Test 1: ringing = ', ringing, trim(clockCurrTime(clock)) + do n = 1, 6 + call ESMF_ClockAdvance(clock,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + print *, ' Test 1: ringing = ', ringing, trim(clockCurrTime(clock)) + if(ringing) nrings = nrings + 1 + enddo + call ESMF_ClockSet(clock, direction = ESMF_DIRECTION_REVERSE, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + do n = 1, 6 + call ESMF_ClockAdvance(clock,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + if(ringing) nrings = nrings + 1 + print *, ' Test 1: ringing = ', ringing, trim(clockCurrTime(clock)) + enddo + rc = ESMF_FAILURE + print *, nrings + if(nrings == 13) rc = ESMF_SUCCESS + end subroutine + + subroutine ForwardReverseAlarm_Test2(rc) + + integer, intent(out) :: rc + + type (ESMF_Clock) :: clock + type (ESMF_Alarm) :: alarm + type (ESMF_Time) :: startTime, stopTime, ringTime + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + + integer :: status, n, nrings=0 + logical :: ringing, enabled, sticky + + rc = ESMF_SUCCESS + print *, 'Forward and Reverse Alarms Tests: ' + call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + ! Test 2: c.t0 = a.t0, c.dt = a.dt = 10 min + print *, 'Test 2: c.t0 = a.t0, c.dt = a.dt = 20 min' + call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeIntervalSet(ringTimeInterval,S=1200, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + clock = ESMF_ClockCreate(timeStep=timeStep,startTime=startTime,stopTime=stopTime,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, ringInterval=ringTimeInterval, enabled=.true., sticky=.false., name='alarm', rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_AlarmDebug(alarm,'test1',rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + if(ringing) nrings = nrings + 1 + print *, 'Test 2: ringing = ', ringing, trim(clockCurrTime(clock)) + do n = 1, 6 + call ESMF_ClockAdvance(clock,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + print *, ' Test 2: ringing = ', ringing, trim(clockCurrTime(clock)) + if(ringing) nrings = nrings + 1 + enddo + call ESMF_ClockSet(clock, direction = ESMF_DIRECTION_REVERSE, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + do n = 1, 6 + call ESMF_ClockAdvance(clock,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + if(ringing) nrings = nrings + 1 + print *, ' Test 2: ringing = ', ringing, trim(clockCurrTime(clock)) + enddo + rc = ESMF_FAILURE + print *, nrings + if(nrings == 7) rc = ESMF_SUCCESS + end subroutine + + subroutine ForwardReverseAlarm_Test3(rc) + + integer, intent(out) :: rc + + type (ESMF_Clock) :: clock + type (ESMF_Alarm) :: alarm + type (ESMF_Time) :: startTime, stopTime, ringTime + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + + integer :: status, n, nrings=0 + logical :: ringing, enabled, sticky + + rc = ESMF_SUCCESS + print *, 'Forward and Reverse Alarms Tests: ' + call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + ! Test 3: c.t0 = a.t0, c.dt = a.dt = 10 min + print *, 'Test 3: c.t0 = a.t0, c.dt = a.dt = 12 min' + call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeIntervalSet(ringTimeInterval,S=720, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + clock = ESMF_ClockCreate(timeStep=timeStep,startTime=startTime,stopTime=stopTime,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, ringInterval=ringTimeInterval, enabled=.true., sticky=.false., name='alarm', rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_AlarmDebug(alarm,'test1',rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + if(ringing) nrings = nrings + 1 + print *, 'Test 3: ringing = ', ringing, trim(clockCurrTime(clock)) + do n = 1, 6 + call ESMF_ClockAdvance(clock,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + print *, ' Test 3: ringing = ', ringing, trim(clockCurrTime(clock)) + if(ringing) nrings = nrings + 1 + enddo + call ESMF_ClockSet(clock, direction = ESMF_DIRECTION_REVERSE, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + do n = 1, 6 + call ESMF_ClockAdvance(clock,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + if(ringing) nrings = nrings + 1 + print *, ' Test 3: ringing = ', ringing, trim(clockCurrTime(clock)) + enddo + rc = ESMF_FAILURE + print *, nrings + if(nrings == 3) rc = ESMF_SUCCESS + end subroutine + end program ESMF_AlarmTest From c61e48786f19e28a777d3c981fd23533e2ce01d3 Mon Sep 17 00:00:00 2001 From: Rocky Dunlap Date: Tue, 3 May 2022 14:49:17 -0600 Subject: [PATCH 09/32] Fix CircleCI config --- .circleci/config.yml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index e80cb9c585..7033fe3e12 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -161,7 +161,8 @@ jobs: destination: doc-artifacts.zip publish-esmf-docs: - machine: true + machine: + image: ubuntu-2004:202201-02 resource_class: medium steps: - restore_cache: @@ -169,7 +170,7 @@ jobs: - esmf-docs-{{ .Revision }} - add_ssh_keys: fingerprints: - - "89:cb:75:34:f4:61:86:8d:78:bc:7d:c0:49:1d:98:36" + - "14:e5:89:bd:fe:9a:28:7e:06:56:f2:0d:93:ff:9a:9c" - run: name: Prep Artifacts command: cd /tmp/artifacts && unzip doc-artifacts.zip @@ -210,7 +211,8 @@ jobs: destination: test_coverage-artifacts.zip publish-test-coverage: - machine: true + machine: + image: ubuntu-2004:202201-02 resource_class: medium steps: - restore_cache: @@ -259,7 +261,8 @@ jobs: destination: api_change-artifacts.zip publish-api-change: - machine: true + machine: + image: ubuntu-2004:202201-02 resource_class: medium steps: - restore_cache: @@ -325,7 +328,8 @@ jobs: destination: doc-esmpy.zip publish-esmpy-docs: - machine: true + machine: + image: ubuntu-2004:202201-02 resource_class: medium steps: - restore_cache: @@ -333,7 +337,7 @@ jobs: - esmpy-docs-{{ .Revision }} - add_ssh_keys: fingerprints: - - "f9:7d:c6:c0:a5:35:f5:57:ac:0c:44:52:4c:b0:be:de" + - "bd:e1:a6:87:3f:d5:fe:18:88:69:eb:55:bf:f9:e4:3d" - run: name: Prep Artifacts command: cd /tmp/artifacts && unzip doc-esmpy.zip From ab6e91f91a6c0f263b92ac32088818e2171bb38a Mon Sep 17 00:00:00 2001 From: Fei Liu Date: Wed, 11 May 2022 11:54:13 -0400 Subject: [PATCH 10/32] Remove argument documentation in alarmget --- .../TimeMgr/interface/ESMF_Alarm.F90 | 33 ------------------- 1 file changed, 33 deletions(-) diff --git a/src/Infrastructure/TimeMgr/interface/ESMF_Alarm.F90 b/src/Infrastructure/TimeMgr/interface/ESMF_Alarm.F90 index db2a8ee37c..81dee0adc8 100644 --- a/src/Infrastructure/TimeMgr/interface/ESMF_Alarm.F90 +++ b/src/Infrastructure/TimeMgr/interface/ESMF_Alarm.F90 @@ -664,44 +664,11 @@ subroutine ESMF_AlarmGet(alarm, keywordEnforcer, & ! The associated clock. ! \item[{[ringTime]}] ! The ring time for a one-shot alarm or the next repeating alarm. -! \item[{[prevRingTime]}] -! The previous ring time. ! \item[{[ringInterval]}] ! The ring interval for repeating (interval) alarms. -! \item[{[stopTime]}] -! The stop time for repeating (interval) alarms. -! \item[{[ringDuration]}] -! The ring duration. Mutually exclusive with -! ringTimeStepCount (see below). -! \item[{[ringTimeStepCount]}] -! The number of time steps comprising the ring duration. Mutually -! exclusive with ringDuration (see above). -! \item[{[timeStepRingingCount]}] -! The number of time steps for which the alarm has been ringing thus -! far. Used internally for tracking ringTimeStepCount ring -! durations (see above). Mutually exclusive with ringBegin -! (see below). Increments in {\tt ESMF\_DIRECTION\_FORWARD} and -! decrements in {\tt ESMF\_DIRECTION\_REVERSE}; -! see Section~\ref{sec:Clock}. -! \item[{[ringBegin]}] -! The time when the alarm began ringing. Used internally for tracking -! ringDuration (see above). Mutually exclusive with -! timeStepRingingCount (see above). -! \item[{[ringEnd]}] -! \begin{sloppypar} -! The time when the alarm ended ringing. Used internally for -! re-ringing alarm in {\tt ESMF\_DIRECTION\_REVERSE}. -! \end{sloppypar} -! \item[{[refTime]}] -! The reference (i.e. base) time for an interval alarm. ! \item[{[ringing]}] ! The current ringing state. ! See also {\tt ESMF\_AlarmRingerOn()}, {\tt ESMF\_AlarmRingerOff()}. -! \item[{[ringingOnPrevTimeStep]}] -! \begin{sloppypar} -! The ringing state upon the previous time step. Same as -! {\tt ESMF\_AlarmWasPrevRinging()}. -! \end{sloppypar} ! \item[{[enabled]}] ! The enabled state. ! See also {\tt ESMF\_AlarmEnable()}, {\tt ESMF\_AlarmDisable()}. From 8cb9422cd862b83d4f7bdcf7430e6d8fdf51bf26 Mon Sep 17 00:00:00 2001 From: Fei Liu Date: Wed, 11 May 2022 11:58:28 -0400 Subject: [PATCH 11/32] Clarify the ringtime argument retrieved by AlarmGet --- src/Infrastructure/TimeMgr/interface/ESMF_Alarm.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Infrastructure/TimeMgr/interface/ESMF_Alarm.F90 b/src/Infrastructure/TimeMgr/interface/ESMF_Alarm.F90 index 81dee0adc8..30d367200c 100644 --- a/src/Infrastructure/TimeMgr/interface/ESMF_Alarm.F90 +++ b/src/Infrastructure/TimeMgr/interface/ESMF_Alarm.F90 @@ -663,7 +663,7 @@ subroutine ESMF_AlarmGet(alarm, keywordEnforcer, & ! \item[{[clock]}] ! The associated clock. ! \item[{[ringTime]}] -! The ring time for a one-shot alarm or the next repeating alarm. +! The associated clock's time at which the alarm is ringing. ! \item[{[ringInterval]}] ! The ring interval for repeating (interval) alarms. ! \item[{[ringing]}] From 29f31e7579191789519f533f66443217dac5eacc Mon Sep 17 00:00:00 2001 From: Fei Liu Date: Mon, 6 Jun 2022 10:43:37 -0400 Subject: [PATCH 12/32] Update alarmCreate for the case ringTime is not specified; clarify the api documentation; add test for the case ringTime is not specified. --- .../TimeMgr/interface/ESMF_Alarm.F90 | 13 ++-- src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C | 52 +++------------ .../TimeMgr/tests/ESMF_AlarmUTest.F90 | 63 +++++++++++++++++++ 3 files changed, 79 insertions(+), 49 deletions(-) diff --git a/src/Infrastructure/TimeMgr/interface/ESMF_Alarm.F90 b/src/Infrastructure/TimeMgr/interface/ESMF_Alarm.F90 index 30d367200c..45eecb96b7 100644 --- a/src/Infrastructure/TimeMgr/interface/ESMF_Alarm.F90 +++ b/src/Infrastructure/TimeMgr/interface/ESMF_Alarm.F90 @@ -332,12 +332,15 @@ function ESMF_AlarmCreateNew(clock, keywordEnforcer, & ! \item[{[ringTime]}] ! The ring time for a one-shot alarm or the first ring time for a ! repeating (interval) alarm. Must specify at least one of ringTime -! or ringInterval. +! or ringInterval. ringTime defaults to clock's current time if +! not specified. ! \item[{[ringInterval]}] -! The ring interval for repeating (interval) alarms. If -! {\tt ringTime} is not also specified (first ring time), it will be -! calculated as the {\tt clock}'s current time plus {\tt ringInterval}. -! Must specify at least one of ringTime or ringInterval. +! The ring interval for repeating (interval) alarms. +! Must specify at least one of ringTime or ringInterval. If ringInterval +! is not specified, the alarm will only ring at ringTime effectively +! making the alarm a one shot alarm. When both ringTime and ringInterval +! are specified, alarm rings intermittently starting at ringTime every +! ringInterval. ! \item[{[enabled]}] ! Sets the enabled state; default is on (true). If disabled, ! an alarm will not function at all. diff --git a/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C b/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C index 5ae986f83b..0f6add0298 100644 --- a/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C +++ b/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C @@ -128,9 +128,11 @@ int Alarm::count=0; sprintf(alarm->name, "Alarm%3.3d", alarm->id); } - if (ringTime != ESMC_NULL_POINTER) { - alarm->ringTime = alarm->prevRingTime = alarm->firstRingTime = *ringTime; - } + if (ringTime != ESMC_NULL_POINTER) + alarm->ringTime = *ringTime; + else + alarm->ringTime = clock->currTime; + if (ringInterval != ESMC_NULL_POINTER) { TimeInterval zeroTimeInterval(0,0,1,0,0,0); if(*ringInterval < zeroTimeInterval){ @@ -146,12 +148,12 @@ int Alarm::count=0; } if( ( *ringInterval == clock->timeStep) ){ - int n = (*ringTime - clock->currTime)/(*ringInterval); + int n = (alarm->ringTime - clock->currTime)/(*ringInterval); //std::cout << n << std::endl; //ringTime->print(); //clock->currTime.print(); //ringInterval->print(); - if(*ringTime != (clock->currTime + n*(*ringInterval)) ){ + if(alarm->ringTime != (clock->currTime + n*(*ringInterval)) ){ ESMC_LogDefault.MsgFoundError(ESMC_RC_ARG_BAD, "; alarm Interval is the same as clock interval, ringTime cannot be misaligned with clock time, alarm will never ring", ESMC_CONTEXT, rc); return 0; @@ -162,20 +164,6 @@ int Alarm::count=0; // LCM albeit it may be very large. alarm->ringInterval = *ringInterval; - // if ringTime not specified, calculate - // ringTime from the current clock time - - // TODO: handle case where *ringTime < clock->currTime; - // same or similar to refTime - - if (ringTime == ESMC_NULL_POINTER) { - // works for positive or negative ringInterval - if(clock->direction == ESMF_DIRECTION_FORWARD) - alarm->ringTime = clock->currTime + alarm->ringInterval; - else - alarm->ringTime = clock->currTime - alarm->ringInterval; - alarm->prevRingTime = alarm->firstRingTime = alarm->ringTime; - } }else{ // A negative ringInterval indicates a one shot alarm at ringTime only TimeInterval zeroTimeInterval(0,0,1,0,0,0); @@ -192,18 +180,9 @@ int Alarm::count=0; } alarm->ringerIsOn = true; - // TODO: invoke private method, shared with Alarm::set(), to calculate - // first ringTime for interval alarms, given ringInterval and none, - // one or both of refTime and ringTime. Will replace logic in - // corresponding above sections. - // this->ringTime > clock->currTime && - // this->ringTime > (passed in) ringTime - returnCode = alarm->Alarm::validate(); if (ESMC_LogDefault.MsgFoundError(returnCode, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) { - // TODO: distinguish non-fatal rc's (warnings, info) at this level (C++), - // and at the F90 level, so isInit flag can be set to usable value. delete alarm; return(ESMC_NULL_POINTER); } else { @@ -213,27 +192,12 @@ int Alarm::count=0; ESMC_LogDefault.MsgFoundError(returnCode, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc); } -// std::vector::iterator it = alarms.begin(); -// while (it++ != alarms.end()){ -// *it = *this; -// } -// for (auto it = begin (alarms); it != end (alarms); ++it) { -// *it = *this; -// } for (int i = 0; i < SAVESIZE; i ++){ alarm->alarms.push_back(*alarm); alarm->clocks.push_back(*clock); } - - //for (Alarm a : alarms) { - // a = *this; - //} - //for (Clock c : clocks) { - // c = this->clock; - //} - - + return(alarm); } // end ESMCI_alarmCreate (new) diff --git a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 index 4f0bae1d39..3f6710c493 100644 --- a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 +++ b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 @@ -1100,6 +1100,16 @@ program ESMF_AlarmTest ! ---------------------------------------------------------------------------- + !EX_UTest + write(failMsg, *) " Did not return ESMF_SUCCESS" + write(name, *) "Forward Alarm Test Case 7" + call ForwardAlarm_Test7(rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), & + name, failMsg, result, ESMF_SRCLINE) + + + ! ---------------------------------------------------------------------------- + !EX_UTest write(failMsg, *) " Did not return ESMF_SUCCESS" write(name, *) "Reverse Alarm Test Case 1" @@ -2199,6 +2209,59 @@ subroutine ForwardAlarm_Test6(rc) rc = ESMF_FAILURE if(nrings == 1) rc = ESMF_SUCCESS end subroutine +!------------------------------------------------------------------------ + subroutine ForwardAlarm_Test7(rc) + + integer, intent(out) :: rc + + type (ESMF_Clock) :: clock + type (ESMF_Alarm) :: alarm + type (ESMF_Time) :: startTime, stopTime, ringTime + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + + integer :: status, n, nrings=0 + logical :: ringing, enabled, sticky + + rc = ESMF_SUCCESS + + call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=30,s=0,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + print *, 'Test 7: c.t0, a.t0 unspecified default to c.t0, c.dt = 10 min a.dt = 10 min' + call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeIntervalSet(ringTimeInterval,S=600, sN=0, sD=1,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_TimeIntervalSet(ringDuration,S=1, sN=0, sD=1,rc=status) + + clock = ESMF_ClockCreate(timeStep=timeStep,startTime=startTime,stopTime=stopTime,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + alarm = ESMF_AlarmCreate(clock, ringInterval=ringTimeInterval, enabled=.true., sticky=.false., name='alarm', rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_AlarmDebug(alarm,'test7',rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + if(ringing) nrings = nrings + 1 + print *, 'Test 7: ringing = ', ringing, trim(clockCurrTime(clock)), ' sticky = ', sticky + do n = 1, 6 + call ESMF_ClockAdvance(clock,rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + if(ringing) nrings = nrings + 1 + print *, ' Test 7: ringing = ', ringing, trim(clockCurrTime(clock)) + enddo + + rc = ESMF_FAILURE + if(nrings == 7) rc = ESMF_SUCCESS + end subroutine + !------------------------------------------------------------------------ ! Reverse Tests From b93fb151e02c93fa4ce29d148320aa2459fca2d2 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Mon, 24 Oct 2022 14:45:07 -0700 Subject: [PATCH 13/32] Set versioning for 8.4.0 release. --- src/Infrastructure/Util/include/ESMC_Macros.h | 6 +++--- src/Infrastructure/Util/src/ESMF_UtilTypes.F90 | 6 +++--- src/addon/NUOPC/doc/NUOPC_howtodoc.ctex | 2 +- src/addon/NUOPC/doc/NUOPC_refdoc.ctex | 2 +- src/doc/ESMC_crefdoc.ctex | 2 +- src/doc/ESMF_refdoc.ctex | 2 +- src/doc/ESMF_usrdoc.ctex | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Infrastructure/Util/include/ESMC_Macros.h b/src/Infrastructure/Util/include/ESMC_Macros.h index 673447ba6b..08ed8d9989 100644 --- a/src/Infrastructure/Util/include/ESMC_Macros.h +++ b/src/Infrastructure/Util/include/ESMC_Macros.h @@ -54,10 +54,10 @@ #define ESMF_VERSION_MINOR 4 #define ESMF_VERSION_REVISION 0 #define ESMF_VERSION_PATCHLEVEL 0 -#define ESMF_VERSION_PUBLIC 'F' -#define ESMF_VERSION_BETASNAPSHOT 'T' +#define ESMF_VERSION_PUBLIC 'T' +#define ESMF_VERSION_BETASNAPSHOT 'F' -#define ESMF_VERSION_STRING "8.4.0 beta snapshot" +#define ESMF_VERSION_STRING "8.4.0" #endif // ESMC_MACROS_H diff --git a/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 b/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 index 900d316542..716c0fbbc7 100644 --- a/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 +++ b/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 @@ -85,10 +85,10 @@ module ESMF_UtilTypesMod integer, parameter :: ESMF_VERSION_MINOR = 4 integer, parameter :: ESMF_VERSION_REVISION = 0 integer, parameter :: ESMF_VERSION_PATCHLEVEL = 0 - logical, parameter :: ESMF_VERSION_PUBLIC = .false. - logical, parameter :: ESMF_VERSION_BETASNAPSHOT = .true. + logical, parameter :: ESMF_VERSION_PUBLIC = .true. + logical, parameter :: ESMF_VERSION_BETASNAPSHOT = .false. - character(*), parameter :: ESMF_VERSION_STRING = "8.4.0 beta snapshot" + character(*), parameter :: ESMF_VERSION_STRING = "8.4.0" #if defined (ESMF_NETCDF) logical, parameter :: ESMF_IO_NETCDF_PRESENT = .true. diff --git a/src/addon/NUOPC/doc/NUOPC_howtodoc.ctex b/src/addon/NUOPC/doc/NUOPC_howtodoc.ctex index 63d3fcc410..25ea037b86 100644 --- a/src/addon/NUOPC/doc/NUOPC_howtodoc.ctex +++ b/src/addon/NUOPC/doc/NUOPC_howtodoc.ctex @@ -17,7 +17,7 @@ \addtolength{\oddsidemargin}{-.75in} \newcommand{\mytitle}{\Large {\bf Building a NUOPC Model}} \newcommand{\myauthors}{\large {\it Content Standards Committee (CSC) Members}} -\newcommand{\myversion}{ESMF 8.4.0 beta snapshot} +\newcommand{\myversion}{ESMF 8.4.0} % set a standard paragraph style \setlength{\parskip}{0pt} \setlength{\parindent}{0pt} diff --git a/src/addon/NUOPC/doc/NUOPC_refdoc.ctex b/src/addon/NUOPC/doc/NUOPC_refdoc.ctex index 5c7d62fded..8e4be48359 100644 --- a/src/addon/NUOPC/doc/NUOPC_refdoc.ctex +++ b/src/addon/NUOPC/doc/NUOPC_refdoc.ctex @@ -17,7 +17,7 @@ \addtolength{\oddsidemargin}{-.75in} \newcommand{\mytitle}{\Large {\bf NUOPC Layer Reference}} \newcommand{\myauthors}{\large {\it Content Standards Committee (CSC) Members}} -\newcommand{\myversion}{ESMF 8.4.0 beta snapshot} +\newcommand{\myversion}{ESMF 8.4.0} % set a standard paragraph style \setlength{\parskip}{0pt} \setlength{\parindent}{0pt} diff --git a/src/doc/ESMC_crefdoc.ctex b/src/doc/ESMC_crefdoc.ctex index 11d9089813..e306392218 100644 --- a/src/doc/ESMC_crefdoc.ctex +++ b/src/doc/ESMC_crefdoc.ctex @@ -14,7 +14,7 @@ \newcommand{\sreq}[1]{\subsection{\hspace{.2in}#1}} \newcommand{\ssreq}[1]{\subsubsection{\hspace{.2in}#1}} \newcommand{\mytitle}{\longname \docmttype ~~} -\newcommand{\myversion}{Version 8.4.0 beta snapshot} +\newcommand{\myversion}{Version 8.4.0} \newenvironment {reqlist} diff --git a/src/doc/ESMF_refdoc.ctex b/src/doc/ESMF_refdoc.ctex index cdd784cc98..d7cbffb578 100644 --- a/src/doc/ESMF_refdoc.ctex +++ b/src/doc/ESMF_refdoc.ctex @@ -15,7 +15,7 @@ \newcommand{\sreq}[1]{\subsection{\hspace{.2in}#1}} \newcommand{\ssreq}[1]{\subsubsection{\hspace{.2in}#1}} \newcommand{\mytitle}{\longname \docmttype ~~} -\newcommand{\myversion}{Version 8.4.0 beta snapshot} +\newcommand{\myversion}{Version 8.4.0} \input{common_commands} diff --git a/src/doc/ESMF_usrdoc.ctex b/src/doc/ESMF_usrdoc.ctex index a427cf0ec8..8fc81811fd 100644 --- a/src/doc/ESMF_usrdoc.ctex +++ b/src/doc/ESMF_usrdoc.ctex @@ -14,7 +14,7 @@ \newcommand{\sreq}[1]{\subsection{\hspace{.2in}#1}} \newcommand{\ssreq}[1]{\subsubsection{\hspace{.2in}#1}} \newcommand{\mytitle}{\longname \docmttype ~~} -\newcommand{\myversion}{Version 8.4.0 beta snapshot} +\newcommand{\myversion}{Version 8.4.0} \newenvironment {reqlist} From ed4d9d6f9ea660a69b989a825faad1bee98f8eeb Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Mon, 24 Oct 2022 14:55:19 -0700 Subject: [PATCH 14/32] Add 'Bill Sacks' to the author list. --- src/doc/ESMC_crefdoc.ctex | 2 +- src/doc/ESMF_refdoc.ctex | 2 +- src/doc/ESMF_usrdoc.ctex | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/ESMC_crefdoc.ctex b/src/doc/ESMC_crefdoc.ctex index e306392218..185f942642 100644 --- a/src/doc/ESMC_crefdoc.ctex +++ b/src/doc/ESMC_crefdoc.ctex @@ -38,7 +38,7 @@ \newcommand{\longname}{ESMF } \newcommand{\funcname}{ESMF } \newcommand{\shortname}{REF} -\newcommand{\myauthors}{ESMF Joint Specification Team: V. Balaji, Byron Boville, Samson Cheung, Tom Clune, Nancy Collins, Tony Craig, Carlos Cruz, Arlindo da Silva, Cecelia DeLuca, Rosalinda de Fainchtein, Rocky Dunlap, Brian Eaton, Steve Goldhaber, Bob Hallberg, Tom Henderson, Chris Hill, Mark Iredell, Joseph Jacob, Rob Jacob, Phil Jones, Brian Kauffman, Erik Kluzek, Ben Koziol, Jay Larson, Peggy Li, Fei Liu, John Michalakes, Raffaele Montuoro, Sylvia Murphy, David Neckels, Ryan O Kuinghttons, Bob Oehmke, Chuck Panaccione, Daniel Rosen, Jim Rosinski, Mathew Rothstein, Kathy Saint, Will Sawyer, Earl Schwab, Shepard Smithline, Walter Spector, Don Stark, Max Suarez, Spencer Swift, Gerhard Theurich, Atanas Trayanov, Silverio Vasquez, Jon Wolfe, Weiyu Yang, Mike Young, Leonid Zaslavsky} +\newcommand{\myauthors}{ESMF Joint Specification Team: V. Balaji, Byron Boville, Samson Cheung, Tom Clune, Nancy Collins, Tony Craig, Carlos Cruz, Arlindo da Silva, Cecelia DeLuca, Rosalinda de Fainchtein, Rocky Dunlap, Brian Eaton, Steve Goldhaber, Bob Hallberg, Tom Henderson, Chris Hill, Mark Iredell, Joseph Jacob, Rob Jacob, Phil Jones, Brian Kauffman, Erik Kluzek, Ben Koziol, Jay Larson, Peggy Li, Fei Liu, John Michalakes, Raffaele Montuoro, Sylvia Murphy, David Neckels, Ryan O Kuinghttons, Bob Oehmke, Chuck Panaccione, Daniel Rosen, Jim Rosinski, Mathew Rothstein, Bill Sacks, Kathy Saint, Will Sawyer, Earl Schwab, Shepard Smithline, Walter Spector, Don Stark, Max Suarez, Spencer Swift, Gerhard Theurich, Atanas Trayanov, Silverio Vasquez, Jon Wolfe, Weiyu Yang, Mike Young, Leonid Zaslavsky} %=============================================================================== \setlength{\textwidth}{6.5truein} \setlength{\textheight}{8.5truein} diff --git a/src/doc/ESMF_refdoc.ctex b/src/doc/ESMF_refdoc.ctex index d7cbffb578..c0d6d6d690 100644 --- a/src/doc/ESMF_refdoc.ctex +++ b/src/doc/ESMF_refdoc.ctex @@ -42,7 +42,7 @@ \newcommand{\longname}{ESMF } \newcommand{\funcname}{ESMF } \newcommand{\shortname}{REF} -\newcommand{\myauthors}{ESMF Joint Specification Team: V. Balaji, Byron Boville, Samson Cheung, Tom Clune, Nancy Collins, Tony Craig, Carlos Cruz, Arlindo da Silva, Cecelia DeLuca, Rosalinda de Fainchtein, Rocky Dunlap, Brian Eaton, Steve Goldhaber, Bob Hallberg, Tom Henderson, Chris Hill, Mark Iredell, Joseph Jacob, Rob Jacob, Phil Jones, Brian Kauffman, Erik Kluzek, Ben Koziol, Jay Larson, Peggy Li, Fei Liu, John Michalakes, Raffaele Montuoro, Sylvia Murphy, David Neckels, Ryan O Kuinghttons, Bob Oehmke, Chuck Panaccione, Daniel Rosen, Jim Rosinski, Mathew Rothstein, Kathy Saint, Will Sawyer, Earl Schwab, Shepard Smithline, Walter Spector, Don Stark, Max Suarez, Spencer Swift, Gerhard Theurich, Atanas Trayanov, Silverio Vasquez, Jon Wolfe, Weiyu Yang, Mike Young, Leonid Zaslavsky} +\newcommand{\myauthors}{ESMF Joint Specification Team: V. Balaji, Byron Boville, Samson Cheung, Tom Clune, Nancy Collins, Tony Craig, Carlos Cruz, Arlindo da Silva, Cecelia DeLuca, Rosalinda de Fainchtein, Rocky Dunlap, Brian Eaton, Steve Goldhaber, Bob Hallberg, Tom Henderson, Chris Hill, Mark Iredell, Joseph Jacob, Rob Jacob, Phil Jones, Brian Kauffman, Erik Kluzek, Ben Koziol, Jay Larson, Peggy Li, Fei Liu, John Michalakes, Raffaele Montuoro, Sylvia Murphy, David Neckels, Ryan O Kuinghttons, Bob Oehmke, Chuck Panaccione, Daniel Rosen, Jim Rosinski, Mathew Rothstein, Bill Sacks, Kathy Saint, Will Sawyer, Earl Schwab, Shepard Smithline, Walter Spector, Don Stark, Max Suarez, Spencer Swift, Gerhard Theurich, Atanas Trayanov, Silverio Vasquez, Jon Wolfe, Weiyu Yang, Mike Young, Leonid Zaslavsky} %=============================================================================== \setlength{\textwidth}{6.5truein} \setlength{\textheight}{8.5truein} diff --git a/src/doc/ESMF_usrdoc.ctex b/src/doc/ESMF_usrdoc.ctex index 8fc81811fd..4bec5800f0 100644 --- a/src/doc/ESMF_usrdoc.ctex +++ b/src/doc/ESMF_usrdoc.ctex @@ -29,7 +29,7 @@ \newcommand{\longname}{ESMF } \newcommand{\funcname}{ESMF } \newcommand{\shortname}{REF} -\newcommand{\myauthors}{ESMF Joint Specification Team: V. Balaji, Byron Boville, Samson Cheung, Tom Clune, Nancy Collins, Tony Craig, Carlos Cruz, Arlindo da Silva, Cecelia DeLuca, Rosalinda de Fainchtein, Rocky Dunlap, Brian Eaton, Steve Goldhaber, Bob Hallberg, Tom Henderson, Chris Hill, Mark Iredell, Joseph Jacob, Rob Jacob, Phil Jones, Brian Kauffman, Erik Kluzek, Ben Koziol, Jay Larson, Peggy Li, Fei Liu, John Michalakes, Raffaele Montuoro, Sylvia Murphy, David Neckels, Ryan O Kuinghttons, Bob Oehmke, Chuck Panaccione, Daniel Rosen, Jim Rosinski, Mathew Rothstein, Kathy Saint, Will Sawyer, Earl Schwab, Shepard Smithline, Walter Spector, Don Stark, Max Suarez, Spencer Swift, Gerhard Theurich, Atanas Trayanov, Silverio Vasquez, Jon Wolfe, Weiyu Yang, Mike Young, Leonid Zaslavsky} +\newcommand{\myauthors}{ESMF Joint Specification Team: V. Balaji, Byron Boville, Samson Cheung, Tom Clune, Nancy Collins, Tony Craig, Carlos Cruz, Arlindo da Silva, Cecelia DeLuca, Rosalinda de Fainchtein, Rocky Dunlap, Brian Eaton, Steve Goldhaber, Bob Hallberg, Tom Henderson, Chris Hill, Mark Iredell, Joseph Jacob, Rob Jacob, Phil Jones, Brian Kauffman, Erik Kluzek, Ben Koziol, Jay Larson, Peggy Li, Fei Liu, John Michalakes, Raffaele Montuoro, Sylvia Murphy, David Neckels, Ryan O Kuinghttons, Bob Oehmke, Chuck Panaccione, Daniel Rosen, Jim Rosinski, Mathew Rothstein, Bill Sacks, Kathy Saint, Will Sawyer, Earl Schwab, Shepard Smithline, Walter Spector, Don Stark, Max Suarez, Spencer Swift, Gerhard Theurich, Atanas Trayanov, Silverio Vasquez, Jon Wolfe, Weiyu Yang, Mike Young, Leonid Zaslavsky} %=============================================================================== \setlength{\textwidth}{6.5truein} \setlength{\textheight}{8.5truein} From cc2575e7b2c5dcaa34ba016c66585e39a5708fb8 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Tue, 25 Jul 2023 15:43:56 -0700 Subject: [PATCH 15/32] Set versioning for 8.5.0 release. --- README.md | 2 +- src/Infrastructure/Util/include/ESMC_Macros.h | 6 +++--- src/Infrastructure/Util/src/ESMF_UtilTypes.F90 | 6 +++--- src/addon/NUOPC/doc/NUOPC_howtodoc.ctex | 2 +- src/addon/NUOPC/doc/NUOPC_refdoc.ctex | 2 +- src/addon/esmpy/pyproject.toml | 2 +- src/doc/ESMC_crefdoc.ctex | 2 +- src/doc/ESMF_refdoc.ctex | 2 +- src/doc/ESMF_usrdoc.ctex | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index d4f415212b..42a35d4913 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ Pre-built binaries for ESMF and ESMPy are available through a number of channels ``` docker run -it --rm esmf/esmf-build-release:latest ``` - Replace `latest` in the above command with a valid version, like `8.4.0`, in order to access a specific ESMF version. + Replace `latest` in the above command with a valid version, like `8.5.0`, in order to access a specific ESMF version. * [Anaconda Conda-Forge](https://anaconda.org/conda-forge/): Under [conda-forge/esmpy](https://anaconda.org/conda-forge/esmpy). To install locally (_note Windows is not supported_), run: ``` diff --git a/src/Infrastructure/Util/include/ESMC_Macros.h b/src/Infrastructure/Util/include/ESMC_Macros.h index 361dc5c7f1..597e0ef328 100644 --- a/src/Infrastructure/Util/include/ESMC_Macros.h +++ b/src/Infrastructure/Util/include/ESMC_Macros.h @@ -54,10 +54,10 @@ #define ESMF_VERSION_MINOR 5 #define ESMF_VERSION_REVISION 0 #define ESMF_VERSION_PATCHLEVEL 0 -#define ESMF_VERSION_PUBLIC 'F' -#define ESMF_VERSION_BETASNAPSHOT 'T' +#define ESMF_VERSION_PUBLIC 'T' +#define ESMF_VERSION_BETASNAPSHOT 'F' -#define ESMF_VERSION_STRING "8.5.0 beta snapshot" +#define ESMF_VERSION_STRING "8.5.0" #endif // ESMC_MACROS_H diff --git a/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 b/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 index 0373f45ff8..f8b1e2acaa 100644 --- a/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 +++ b/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 @@ -85,10 +85,10 @@ module ESMF_UtilTypesMod integer, parameter :: ESMF_VERSION_MINOR = 5 integer, parameter :: ESMF_VERSION_REVISION = 0 integer, parameter :: ESMF_VERSION_PATCHLEVEL = 0 - logical, parameter :: ESMF_VERSION_PUBLIC = .false. - logical, parameter :: ESMF_VERSION_BETASNAPSHOT = .true. + logical, parameter :: ESMF_VERSION_PUBLIC = .true. + logical, parameter :: ESMF_VERSION_BETASNAPSHOT = .false. - character(*), parameter :: ESMF_VERSION_STRING = "8.5.0 beta snapshot" + character(*), parameter :: ESMF_VERSION_STRING = "8.5.0" #if defined (ESMF_NETCDF) logical, parameter :: ESMF_IO_NETCDF_PRESENT = .true. diff --git a/src/addon/NUOPC/doc/NUOPC_howtodoc.ctex b/src/addon/NUOPC/doc/NUOPC_howtodoc.ctex index 9eaceccff5..c9a98d383b 100644 --- a/src/addon/NUOPC/doc/NUOPC_howtodoc.ctex +++ b/src/addon/NUOPC/doc/NUOPC_howtodoc.ctex @@ -17,7 +17,7 @@ \addtolength{\oddsidemargin}{-.75in} \newcommand{\mytitle}{\Large {\bf Building a NUOPC Model}} \newcommand{\myauthors}{\large {\it Content Standards Committee (CSC) Members}} -\newcommand{\myversion}{ESMF 8.5.0 beta snapshot} +\newcommand{\myversion}{ESMF 8.5.0} % set a standard paragraph style \setlength{\parskip}{0pt} \setlength{\parindent}{0pt} diff --git a/src/addon/NUOPC/doc/NUOPC_refdoc.ctex b/src/addon/NUOPC/doc/NUOPC_refdoc.ctex index 14d1700fb7..a2bfe23f61 100644 --- a/src/addon/NUOPC/doc/NUOPC_refdoc.ctex +++ b/src/addon/NUOPC/doc/NUOPC_refdoc.ctex @@ -17,7 +17,7 @@ \addtolength{\oddsidemargin}{-.75in} \newcommand{\mytitle}{\Large {\bf NUOPC Layer Reference}} \newcommand{\myauthors}{\large {\it Content Standards Committee (CSC) Members}} -\newcommand{\myversion}{ESMF 8.5.0 beta snapshot} +\newcommand{\myversion}{ESMF 8.5.0} % set a standard paragraph style \setlength{\parskip}{0pt} \setlength{\parindent}{0pt} diff --git a/src/addon/esmpy/pyproject.toml b/src/addon/esmpy/pyproject.toml index ed5656b73c..0d2f68e19b 100644 --- a/src/addon/esmpy/pyproject.toml +++ b/src/addon/esmpy/pyproject.toml @@ -33,7 +33,7 @@ enabled = true template = "{tag}" dev_template = "{tag}" dirty_template = "{tag}" -starting_version = "8.5.0beta" # this is a backup for pip <= 22.0 where git-versioning doesn't work +starting_version = "8.5.0" # this is a backup for pip <= 22.0 where git-versioning doesn't work [tool.dynamic] version = "placeholder" # this is a placeholder for the version pulled with git-versioning diff --git a/src/doc/ESMC_crefdoc.ctex b/src/doc/ESMC_crefdoc.ctex index d0c385a611..d0503ead2c 100644 --- a/src/doc/ESMC_crefdoc.ctex +++ b/src/doc/ESMC_crefdoc.ctex @@ -14,7 +14,7 @@ \newcommand{\sreq}[1]{\subsection{\hspace{.2in}#1}} \newcommand{\ssreq}[1]{\subsubsection{\hspace{.2in}#1}} \newcommand{\mytitle}{\longname \docmttype ~~} -\newcommand{\myversion}{Version 8.5.0 beta snapshot} +\newcommand{\myversion}{Version 8.5.0} \newenvironment {reqlist} diff --git a/src/doc/ESMF_refdoc.ctex b/src/doc/ESMF_refdoc.ctex index f79f2651e6..a47cb08110 100644 --- a/src/doc/ESMF_refdoc.ctex +++ b/src/doc/ESMF_refdoc.ctex @@ -15,7 +15,7 @@ \newcommand{\sreq}[1]{\subsection{\hspace{.2in}#1}} \newcommand{\ssreq}[1]{\subsubsection{\hspace{.2in}#1}} \newcommand{\mytitle}{\longname \docmttype ~~} -\newcommand{\myversion}{Version 8.5.0 beta snapshot} +\newcommand{\myversion}{Version 8.5.0} \input{common_commands} diff --git a/src/doc/ESMF_usrdoc.ctex b/src/doc/ESMF_usrdoc.ctex index 0bd57fa920..d8984999de 100644 --- a/src/doc/ESMF_usrdoc.ctex +++ b/src/doc/ESMF_usrdoc.ctex @@ -14,7 +14,7 @@ \newcommand{\sreq}[1]{\subsection{\hspace{.2in}#1}} \newcommand{\ssreq}[1]{\subsubsection{\hspace{.2in}#1}} \newcommand{\mytitle}{\longname \docmttype ~~} -\newcommand{\myversion}{Version 8.5.0 beta snapshot} +\newcommand{\myversion}{Version 8.5.0} \newenvironment {reqlist} From ca0dbc89af21bca2c4071f6519b7f33be0fd95ee Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Thu, 26 Dec 2024 09:16:19 -0700 Subject: [PATCH 16/32] Change "newalarm" reference to "alarm" --- src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C b/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C index db8e2b4d4d..88a484d169 100644 --- a/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C +++ b/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C @@ -1124,7 +1124,7 @@ bool Alarm::canRingAtNextTime(Clock & clock, TimeInterval * timeStep) const { // must be associated with a clock if(clock == ESMC_NULL_POINTER) { char logMsg[2*ESMF_MAXSTR]; - sprintf(logMsg, "newalarm %s is not associated with any clock.", name); + sprintf(logMsg, "alarm %s is not associated with any clock.", name); ESMC_LogDefault.Write(logMsg, ESMC_LOGMSG_WARN,ESMC_CONTEXT); return(false); } From 870904e0da45be4a25afb8134f13d6d824e0cffc Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Thu, 26 Dec 2024 11:40:22 -0700 Subject: [PATCH 17/32] Add missing !EX_UTest labels --- src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 index 36038fc4b0..ee02c6bdfc 100644 --- a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 +++ b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 @@ -1191,6 +1191,7 @@ program ESMF_AlarmTest ! ---------------------------------------------------------------------------- + !EX_UTest write(failMsg, *) " Alarms with ClockSet... " write(name, *) "Test ClockSet after alarm attached to clock " rc = ESMF_SUCCESS @@ -1203,6 +1204,7 @@ program ESMF_AlarmTest ! ---------------------------------------------------------------------------- + !EX_UTest ! The following tests are from Ben@NASA's support ticket 3614994 write(failMsg, *) " Alarms did not rewind correct number of times " write(name, *) "Test multiple alarms rewind correct number of times " @@ -1215,6 +1217,7 @@ program ESMF_AlarmTest ! ---------------------------------------------------------------------------- + !EX_UTest write(failMsg, *) " Alarms hang... " write(name, *) "Test multiple alarms replay without hanging " rc = ESMF_SUCCESS @@ -1226,6 +1229,7 @@ program ESMF_AlarmTest ! ---------------------------------------------------------------------------- + !EX_UTest write(failMsg, *) " Alarms with ring intervals equal to clock interval, incorrect behavior " write(name, *) "Test running an alarms forward-reverse-forward with ring interval equal to clock interval " rc = ESMF_SUCCESS @@ -1237,6 +1241,7 @@ program ESMF_AlarmTest ! ---------------------------------------------------------------------------- + !EX_UTest write(failMsg, *) " Alarms reverse with sticky set... " write(name, *) "Test running an alarm reverse with sticky bit set " rc = ESMF_SUCCESS @@ -1249,6 +1254,7 @@ program ESMF_AlarmTest ! ---------------------------------------------------------------------------- #if 1 + !EX_UTest write(failMsg, *) " Alarms with getPrevRingTime... " write(name, *) "Test getPrevRingTime... after alarm attached to clock " rc = ESMF_SUCCESS From 65b1e78d4e79d36e85a91ace2a9b7bedf834343c Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Fri, 27 Dec 2024 14:59:44 -0700 Subject: [PATCH 18/32] Clean up Forward and Reverse alarm tests and make them more rigorous --- .../TimeMgr/tests/ESMF_AlarmUTest.F90 | 491 ++++++++++-------- 1 file changed, 283 insertions(+), 208 deletions(-) diff --git a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 index ee02c6bdfc..ed792116ff 100644 --- a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 +++ b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 @@ -86,7 +86,6 @@ program ESMF_AlarmTest ! instantiate timestep, start and stop times type(ESMF_TimeInterval) :: TIMEINTERVAL_HISTORY, alarmStep, alarmStep2 - type(ESMF_TimeInterval) :: runDuration, ringDuration type(ESMF_Time) :: currentTime, currTime, afterAlarmTime, beforeAlarmTime type(ESMF_Time) :: alarmStopTime, nextTime, prevTime, currentTime2, time1 @@ -1913,16 +1912,21 @@ character*64 function clockCurrTime(clock) ! Forward Tests !------------------------------------------------------------------------ subroutine ForwardAlarm_Test1(rc) + ! Test 1: c.t0 = a.t0, c.dt = a.dt = 10 min integer, intent(out) :: rc type (ESMF_Clock) :: clock type (ESMF_Alarm) :: alarm type (ESMF_Time) :: startTime, stopTime, ringTime - type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval - integer :: status, n, nrings=0 + integer :: status, n logical :: ringing, enabled, sticky + logical :: allCorrect + + rc = ESMF_FAILURE + allCorrect = .true. call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() @@ -1931,8 +1935,6 @@ subroutine ForwardAlarm_Test1(rc) call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - ! Test 1: c.t0 = a.t0, c.dt = a.dt = 10 min - print *, 'Test 1: c.t0 = a.t0, c.dt = a.dt = 10 min' call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_TimeIntervalSet(ringTimeInterval,S=600, sN=0, sD=1,rc=status) @@ -1947,32 +1949,40 @@ subroutine ForwardAlarm_Test1(rc) call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - print *, 'Test 1: ringing = ', ringing, trim(clockCurrTime(clock)) - if(ringing) nrings = nrings + 1 + if (.not. ringing) then + allCorrect = .false. + end if do n = 1, 6 call ESMF_ClockAdvance(clock,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - if(ringing) nrings = nrings + 1 - print *, ' Test 1: ringing = ', ringing, trim(clockCurrTime(clock)) + if (.not. ringing) then + allCorrect = .false. + end if enddo - rc = ESMF_FAILURE - if(nrings == 7) rc = ESMF_SUCCESS + if (allCorrect) then + rc = ESMF_SUCCESS + end if end subroutine !------------------------------------------------------------------------ subroutine ForwardAlarm_Test2(rc) + ! Test 2: c.t0 = a.t0, c.dt = 10 min, a.dt = 20 min integer, intent(out) :: rc type (ESMF_Clock) :: clock type (ESMF_Alarm) :: alarm type (ESMF_Time) :: startTime, stopTime, ringTime - type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval - integer :: status, n, nrings=0 + integer :: status, n logical :: ringing, enabled, sticky + logical :: allCorrect + + rc = ESMF_FAILURE + allCorrect = .true. call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() @@ -1981,7 +1991,6 @@ subroutine ForwardAlarm_Test2(rc) call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - print *, 'Test 2: c.t0 = a.t0, c.dt = 10 min a.dt = 20 min' call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_TimeIntervalSet(ringTimeInterval,S=1200, sN=0, sD=1,rc=status) @@ -1996,35 +2005,50 @@ subroutine ForwardAlarm_Test2(rc) call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - print *, 'Test 2: ringing = ', ringing, trim(clockCurrTime(clock)) - if(ringing) nrings = nrings + 1 + if (.not. ringing) then + allCorrect = .false. + end if do n = 1, 6 call ESMF_ClockAdvance(clock,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - print *, ' Test 2: ringing = ', ringing, trim(clockCurrTime(clock)) - if(ringing) nrings = nrings + 1 + if (modulo(n,2) == 0) then + ! Alarm should be ringing on even time steps + if (.not. ringing) then + allCorrect = .false. + end if + else + ! Alarm should NOT be ringing on odd time steps + if (ringing) then + allCorrect = .false. + end if + end if enddo - rc = ESMF_FAILURE - if(nrings == 4) rc = ESMF_SUCCESS + if (allCorrect) then + rc = ESMF_SUCCESS + end if end subroutine !------------------------------------------------------------------------ subroutine ForwardAlarm_Test3(rc) + ! Test 3: c.t0 = a.t0, c.dt = 20 min, a.dt = 10 min + ! + ! This should raise an error: it's an error to create an alarm with alarm timeInterval + ! less than clock timeStep integer, intent(out) :: rc type (ESMF_Clock) :: clock type (ESMF_Alarm) :: alarm type (ESMF_Time) :: startTime, stopTime, ringTime - type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval - integer :: status, n, nrings=0 + integer :: status, n logical :: ringing, enabled, sticky - rc = ESMF_SUCCESS - !print *, 'Test 3: c.t0 = a.t0, c.dt = 20 min a.dt = 10 min' + rc = ESMF_FAILURE + call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) @@ -2042,37 +2066,33 @@ subroutine ForwardAlarm_Test3(rc) ! It's an error to create an alarm with alarm timeInterval less than clock timeStep alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, ringInterval=ringTimeInterval, enabled=.true., sticky=.false., name='alarm', rc=status) - if(status /= ESMF_SUCCESS) return - call ESMF_AlarmDebug(alarm,'test3',rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() - - call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() - print *, 'Test 3: ringing = ', ringing, trim(clockCurrTime(clock)) - do n = 1, 6 - call ESMF_ClockAdvance(clock,rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() - call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() - print *, ' Test 3: ringing = ', ringing, trim(clockCurrTime(clock)) - enddo - - rc = ESMF_FAILURE + if(status /= ESMF_SUCCESS) then + ! This is the expected result: the status of ESMF_AlarmCreate should be an error, so + ! in this case, this test returns SUCCESS + rc = ESMF_SUCCESS + else + ! On the other hand, if ESMF_AlarmCreate succeeded, then this test has failed + rc = ESMF_FAILURE + end if + !call ESMF_AlarmDebug(alarm,'test3',rc=status) end subroutine !------------------------------------------------------------------------ subroutine ForwardAlarm_Test4(rc) + ! Test 4: c.t0 = a.t0, c.dt = 10 min, a.dt = 12 min integer, intent(out) :: rc type (ESMF_Clock) :: clock type (ESMF_Alarm) :: alarm type (ESMF_Time) :: startTime, stopTime, ringTime - type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval - integer :: status, n, nrings=0 + integer :: status, n logical :: ringing, enabled, sticky + logical :: allCorrect - rc = ESMF_SUCCESS + rc = ESMF_FAILURE + allCorrect = .true. call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() @@ -2081,62 +2101,73 @@ subroutine ForwardAlarm_Test4(rc) call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - ! Test 4: c.t0 = a.t0, c.dt = 10 min a.dt = 12 min - print *, 'Test 4: c.t0 = a.t0, c.dt = 10 min a.dt = 12 min' call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_TimeIntervalSet(ringTimeInterval,S=720, sN=0, sD=1,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - call ESMF_TimeIntervalSet(ringDuration,S=1, sN=0, sD=1,rc=status) clock = ESMF_ClockCreate(timeStep=timeStep,startTime=startTime,stopTime=stopTime,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, ringInterval=ringTimeInterval, enabled=.true., sticky=.false., name='alarm', rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - call ESMF_AlarmDebug(alarm,'test4',rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() - - write(*, '(A20,Z16)') 'LOC(sticky) = ', LOC(sticky) + ! call ESMF_AlarmDebug(alarm,'test4',rc=status) + ! if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - if(ringing) nrings = nrings + 1 - print *, 'Test 4: ringing = ', ringing, trim(clockCurrTime(clock)), ' sticky = ', sticky + if (.not. ringing) then + allCorrect = .false. + end if + do n = 1, 6 call ESMF_ClockAdvance(clock,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - if(ringing) nrings = nrings + 1 - print *, ' Test 4: ringing = ', ringing, trim(clockCurrTime(clock)) + if (n == 6) then + ! Alarm should be ringing on the 6th time step, when alarm dt aligns with clock dt + if (.not. ringing) then + allCorrect = .false. + end if + else + ! Alarm should NOT be ringing on other time steps + if (ringing) then + allCorrect = .false. + end if + end if enddo - rc = ESMF_FAILURE - if(nrings == 2) rc = ESMF_SUCCESS + if (allCorrect) then + rc = ESMF_SUCCESS + end if end subroutine !------------------------------------------------------------------------ subroutine ForwardAlarm_Test5(rc) + ! Test 5: c.t0 = 00:00:00, a.t0=00:04:00, c.dt = a.dt = 10 min, sticky (an alarm won't ring) + ! + ! This should raise an error: it's an error to create an alarm where the alarm interval + ! is the same as clock interval but ringTime is misaligned with clock time: in this + ! case, the alarm will never ring. integer, intent(out) :: rc type (ESMF_Clock) :: clock type (ESMF_Alarm) :: alarm type (ESMF_Time) :: startTime, stopTime, ringTime - type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval - integer :: status, n, nrings=0 + integer :: status, n logical :: ringing, enabled, sticky - rc = ESMF_SUCCESS + rc = ESMF_FAILURE call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) + call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=4,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - print *, 'Test 5: c.t0 = 0:0:0 a.t0=0:4:0, c.dt = a.dt = 10 min sticky (an alarm wont ring)' call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_TimeIntervalSet(ringTimeInterval,S=600, sN=0, sD=1,rc=status) @@ -2144,38 +2175,36 @@ subroutine ForwardAlarm_Test5(rc) clock = ESMF_ClockCreate(timeStep=timeStep,startTime=startTime,stopTime=stopTime,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=4,s=0,rc=status) alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, ringInterval=ringTimeInterval, enabled=.true., sticky=.true., name='alarm', rc=status) - if(status /= ESMF_SUCCESS) return - call ESMF_AlarmDebug(alarm,'test5',rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() - - call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() - print *, 'Test 5: ringing = ', ringing, trim(clockCurrTime(clock)) - do n = 1, 6 - call ESMF_ClockAdvance(clock,rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() - call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() - print *, ' Test 5: ringing = ', ringing, trim(clockCurrTime(clock)) - enddo + if(status /= ESMF_SUCCESS) then + ! This is the expected result: the status of ESMF_AlarmCreate should be an error, so + ! in this case, this test returns SUCCESS + rc = ESMF_SUCCESS + else + ! On the other hand, if ESMF_AlarmCreate succeeded, then this test has failed + rc = ESMF_FAILURE + end if + ! call ESMF_AlarmDebug(alarm,'test5',rc=status) + ! if(status /= ESMF_SUCCESS) call ESMF_Finalize() end subroutine !------------------------------------------------------------------------ subroutine ForwardAlarm_Test6(rc) + ! Test 6: c.t0 = 00:00:00, a.t0 = 00:30:00, c.dt = 10 min, a.dt = unspecified (one shot) integer, intent(out) :: rc type (ESMF_Clock) :: clock type (ESMF_Alarm) :: alarm type (ESMF_Time) :: startTime, stopTime, ringTime - type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + type (ESMF_TimeInterval) :: timeStep - integer :: status, n, nrings=0 + integer :: status, n logical :: ringing, enabled, sticky + logical :: allCorrect - rc = ESMF_SUCCESS + rc = ESMF_FAILURE + allCorrect = .true. call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() @@ -2184,88 +2213,98 @@ subroutine ForwardAlarm_Test6(rc) call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=30,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - ! Test 6: c.t0 = a.t0, c.dt = 10 min a.dt = 12 min - print *, 'Test 6: c.t0 = a.t0, c.dt = 10 min a.dt = unspecified (one shot)' call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - call ESMF_TimeIntervalSet(ringTimeInterval,S=720, sN=0, sD=1,rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() - call ESMF_TimeIntervalSet(ringDuration,S=1, sN=0, sD=1,rc=status) clock = ESMF_ClockCreate(timeStep=timeStep,startTime=startTime,stopTime=stopTime,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, enabled=.true., sticky=.false., name='alarm', rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - call ESMF_AlarmDebug(alarm,'test6',rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() + ! call ESMF_AlarmDebug(alarm,'test6',rc=status) + ! if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - if(ringing) nrings = nrings + 1 - print *, 'Test 6: ringing = ', ringing, trim(clockCurrTime(clock)), ' sticky = ', sticky + if (ringing) then + allCorrect = .false. + end if do n = 1, 6 call ESMF_ClockAdvance(clock,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - if(ringing) nrings = nrings + 1 - print *, ' Test 6: ringing = ', ringing, trim(clockCurrTime(clock)) + if (n == 3) then + ! Alarm should be ringing on the 3rd time step, when the clock time should match + ! the alarm's initial time + if (.not. ringing) then + allCorrect = .false. + end if + else + ! Alarm should NOT be ringing on other time steps + if (ringing) then + allCorrect = .false. + end if + end if enddo - rc = ESMF_FAILURE - if(nrings == 1) rc = ESMF_SUCCESS + if (allCorrect) then + rc = ESMF_SUCCESS + end if + end subroutine !------------------------------------------------------------------------ subroutine ForwardAlarm_Test7(rc) + ! Test 7: c.t0, a.t0 unspecified default to c.t0, c.dt = 10 min, a.dt = 10 min integer, intent(out) :: rc type (ESMF_Clock) :: clock type (ESMF_Alarm) :: alarm - type (ESMF_Time) :: startTime, stopTime, ringTime - type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + type (ESMF_Time) :: startTime, stopTime + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval - integer :: status, n, nrings=0 + integer :: status, n logical :: ringing, enabled, sticky + logical :: allCorrect - rc = ESMF_SUCCESS + rc = ESMF_FAILURE + allCorrect = .true. call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=30,s=0,rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() - print *, 'Test 7: c.t0, a.t0 unspecified default to c.t0, c.dt = 10 min a.dt = 10 min' call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_TimeIntervalSet(ringTimeInterval,S=600, sN=0, sD=1,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - call ESMF_TimeIntervalSet(ringDuration,S=1, sN=0, sD=1,rc=status) clock = ESMF_ClockCreate(timeStep=timeStep,startTime=startTime,stopTime=stopTime,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() alarm = ESMF_AlarmCreate(clock, ringInterval=ringTimeInterval, enabled=.true., sticky=.false., name='alarm', rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - call ESMF_AlarmDebug(alarm,'test7',rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() + ! call ESMF_AlarmDebug(alarm,'test7',rc=status) + ! if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - if(ringing) nrings = nrings + 1 - print *, 'Test 7: ringing = ', ringing, trim(clockCurrTime(clock)), ' sticky = ', sticky + if (.not. ringing) then + allCorrect = .false. + end if do n = 1, 6 call ESMF_ClockAdvance(clock,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - if(ringing) nrings = nrings + 1 - print *, ' Test 7: ringing = ', ringing, trim(clockCurrTime(clock)) + if (.not. ringing) then + allCorrect = .false. + end if enddo - rc = ESMF_FAILURE - if(nrings == 7) rc = ESMF_SUCCESS + if (allCorrect) then + rc = ESMF_SUCCESS + end if end subroutine @@ -2273,16 +2312,21 @@ subroutine ForwardAlarm_Test7(rc) ! Reverse Tests !------------------------------------------------------------------------ subroutine ReverseAlarm_Test1(rc) + ! Test 1: c.t0 = a.t0, c.dt = a.dt = 10 min, time reversed integer, intent(out) :: rc type (ESMF_Clock) :: clock type (ESMF_Alarm) :: alarm type (ESMF_Time) :: startTime, stopTime, ringTime, currTime - type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval - integer :: status, n, nrings=0 + integer :: status, n logical :: ringing, enabled, sticky + logical :: allCorrect + + rc = ESMF_FAILURE + allCorrect = .true. call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() @@ -2291,8 +2335,6 @@ subroutine ReverseAlarm_Test1(rc) call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - ! Test 1: c.t0 = a.t0, c.dt = a.dt = -10 min - print *, 'Test 1: c.t0 = a.t0, c.dt = a.dt = 10 min' call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_TimeIntervalSet(ringTimeInterval,S=600, sN=0, sD=1,rc=status) @@ -2309,32 +2351,40 @@ subroutine ReverseAlarm_Test1(rc) call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - print *, 'Test 1: ringing = ', ringing, trim(clockCurrTime(clock)) - if(ringing) nrings = nrings + 1 + if (.not. ringing) then + allCorrect = .false. + end if do n = 1, 6 call ESMF_ClockAdvance(clock,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - if(ringing) nrings = nrings + 1 - print *, ' Test 1: ringing = ', ringing, trim(clockCurrTime(clock)) + if (.not. ringing) then + allCorrect = .false. + end if enddo - rc = ESMF_FAILURE - if(nrings == 7) rc = ESMF_SUCCESS + if (allCorrect) then + rc = ESMF_SUCCESS + end if end subroutine !------------------------------------------------------------------------ subroutine ReverseAlarm_Test2(rc) + ! Test 2: c.t0 = a.t0, c.dt = 10 min, a.dt = 20 min, time reversed integer, intent(out) :: rc type (ESMF_Clock) :: clock type (ESMF_Alarm) :: alarm type (ESMF_Time) :: startTime, stopTime, ringTime - type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval - integer :: status, n, nrings=0 + integer :: status, n logical :: ringing, enabled, sticky + logical :: allCorrect + + rc = ESMF_FAILURE + allCorrect = .true. call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() @@ -2343,7 +2393,6 @@ subroutine ReverseAlarm_Test2(rc) call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - print *, 'Test 2: c.t0 = a.t0, c.dt = 10 min a.dt = 20 min' call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_TimeIntervalSet(ringTimeInterval,S=1200, sN=0, sD=1,rc=status) @@ -2360,35 +2409,50 @@ subroutine ReverseAlarm_Test2(rc) call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - print *, 'Test 2: ringing = ', ringing, trim(clockCurrTime(clock)) - if(ringing) nrings = nrings + 1 + if (.not. ringing) then + allCorrect = .false. + end if do n = 1, 6 call ESMF_ClockAdvance(clock,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - print *, ' Test 2: ringing = ', ringing, trim(clockCurrTime(clock)) - if(ringing) nrings = nrings + 1 + if (modulo(n,2) == 0) then + ! Alarm should be ringing on even time steps + if (.not. ringing) then + allCorrect = .false. + end if + else + ! Alarm should NOT be ringing on odd time steps + if (ringing) then + allCorrect = .false. + end if + end if enddo - rc = ESMF_FAILURE - if(nrings == 4) rc = ESMF_SUCCESS + if (allCorrect) then + rc = ESMF_SUCCESS + end if end subroutine !------------------------------------------------------------------------ subroutine ReverseAlarm_Test3(rc) + ! Test 3: c.t0 = a.t0, c.dt = 20 min, a.dt = 10 min, time reversed + ! + ! This should raise an error: it's an error to create an alarm with alarm timeInterval + ! less than clock timeStep integer, intent(out) :: rc type (ESMF_Clock) :: clock type (ESMF_Alarm) :: alarm type (ESMF_Time) :: startTime, stopTime, ringTime - type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval - integer :: status, n, nrings=0 + integer :: status, n logical :: ringing, enabled, sticky - rc = ESMF_SUCCESS - !print *, 'Test 3: c.t0 = a.t0, c.dt = 20 min a.dt = 10 min' + rc = ESMF_FAILURE + call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) @@ -2408,37 +2472,33 @@ subroutine ReverseAlarm_Test3(rc) ! It's an error to create an alarm with alarm timeInterval less than clock timeStep alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, ringInterval=ringTimeInterval, enabled=.true., sticky=.false., name='alarm', rc=status) - if(status /= ESMF_SUCCESS) return - call ESMF_AlarmDebug(alarm,'test3',rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() - - call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() - print *, 'Test 3: ringing = ', ringing, trim(clockCurrTime(clock)) - do n = 1, 6 - call ESMF_ClockAdvance(clock,rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() - call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() - print *, ' Test 3: ringing = ', ringing, trim(clockCurrTime(clock)) - enddo - - rc = ESMF_FAILURE + if(status /= ESMF_SUCCESS) then + ! This is the expected result: the status of ESMF_AlarmCreate should be an error, so + ! in this case, this test returns SUCCESS + rc = ESMF_SUCCESS + else + ! On the other hand, if ESMF_AlarmCreate succeeded, then this test has failed + rc = ESMF_FAILURE + end if + !call ESMF_AlarmDebug(alarm,'test3',rc=status) end subroutine !------------------------------------------------------------------------ subroutine ReverseAlarm_Test4(rc) + ! Test 4: c.t0 = a.t0, c.dt = 10 min, a.dt = 12 min, time reversed integer, intent(out) :: rc type (ESMF_Clock) :: clock type (ESMF_Alarm) :: alarm type (ESMF_Time) :: startTime, stopTime, ringTime - type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval - integer :: status, n, nrings=0 + integer :: status, n logical :: ringing, enabled, sticky + logical :: allCorrect - rc = ESMF_SUCCESS + rc = ESMF_FAILURE + allCorrect = .true. call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() @@ -2447,13 +2507,10 @@ subroutine ReverseAlarm_Test4(rc) call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - ! Test 4: c.t0 = a.t0, c.dt = 10 min a.dt = 12 min - print *, 'Test 4: c.t0 = a.t0, c.dt = 10 min a.dt = 12 min' call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_TimeIntervalSet(ringTimeInterval,S=720, sN=0, sD=1,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - call ESMF_TimeIntervalSet(ringDuration,S=1, sN=0, sD=1,rc=status) clock = ESMF_ClockCreate(timeStep=timeStep,startTime=startTime,stopTime=stopTime,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() @@ -2461,50 +2518,63 @@ subroutine ReverseAlarm_Test4(rc) if(status /= ESMF_SUCCESS) call ESMF_Finalize() alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, ringInterval=ringTimeInterval, enabled=.true., sticky=.false., name='alarm', rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - call ESMF_AlarmDebug(alarm,'test4',rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() - - write(*, '(A20,Z16)') 'LOC(sticky) = ', LOC(sticky) + ! call ESMF_AlarmDebug(alarm,'test4',rc=status) + ! if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - if(ringing) nrings = nrings + 1 - print *, 'Test 4: ringing = ', ringing, trim(clockCurrTime(clock)), ' sticky = ', sticky + if (.not. ringing) then + allCorrect = .false. + end if do n = 1, 6 call ESMF_ClockAdvance(clock,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - if(ringing) nrings = nrings + 1 - print *, ' Test 4: ringing = ', ringing, trim(clockCurrTime(clock)) + if (n == 6) then + ! Alarm should be ringing on the 6th time step, when alarm dt aligns with clock dt + if (.not. ringing) then + allCorrect = .false. + end if + else + ! Alarm should NOT be ringing on other time steps + if (ringing) then + allCorrect = .false. + end if + end if enddo - rc = ESMF_FAILURE - if(nrings == 2) rc = ESMF_SUCCESS + if (allCorrect) then + rc = ESMF_SUCCESS + end if end subroutine !------------------------------------------------------------------------ subroutine ReverseAlarm_Test5(rc) + ! Test 5: c.t0 = 00:00:00, a.t0=00:04:00, c.dt = a.dt = 10 min, sticky, time reversed (an alarm won't ring) + ! + ! This should raise an error: it's an error to create an alarm where the alarm interval + ! is the same as clock interval but ringTime is misaligned with clock time: in this + ! case, the alarm will never ring. integer, intent(out) :: rc type (ESMF_Clock) :: clock type (ESMF_Alarm) :: alarm type (ESMF_Time) :: startTime, stopTime, ringTime - type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval - integer :: status, n, nrings=0 + integer :: status, n logical :: ringing, enabled, sticky - rc = ESMF_SUCCESS + rc = ESMF_FAILURE call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) + call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=4,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - print *, 'Test 5: c.t0 = 0:0:0 a.t0=0:4:0, c.dt = a.dt = 10 min sticky (an alarm wont ring)' call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_TimeIntervalSet(ringTimeInterval,S=600, sN=0, sD=1,rc=status) @@ -2514,38 +2584,36 @@ subroutine ReverseAlarm_Test5(rc) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_ClockSet(clock, currTime = stopTime, direction=ESMF_DIRECTION_REVERSE, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=4,s=0,rc=status) alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, ringInterval=ringTimeInterval, enabled=.true., sticky=.true., name='alarm', rc=status) - if(status /= ESMF_SUCCESS) return - call ESMF_AlarmDebug(alarm,'test5',rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() - - call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() - print *, 'Test 5: ringing = ', ringing, trim(clockCurrTime(clock)) - do n = 1, 6 - call ESMF_ClockAdvance(clock,rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() - call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() - print *, ' Test 5: ringing = ', ringing, trim(clockCurrTime(clock)) - enddo + if(status /= ESMF_SUCCESS) then + ! This is the expected result: the status of ESMF_AlarmCreate should be an error, so + ! in this case, this test returns SUCCESS + rc = ESMF_SUCCESS + else + ! On the other hand, if ESMF_AlarmCreate succeeded, then this test has failed + rc = ESMF_FAILURE + end if + ! call ESMF_AlarmDebug(alarm,'test5',rc=status) + ! if(status /= ESMF_SUCCESS) call ESMF_Finalize() end subroutine !------------------------------------------------------------------------ subroutine ReverseAlarm_Test6(rc) + ! Test 6: c.t0 = 00:00:00, a.t0 = 00:30:00, c.dt = 10 min, a.dt = unspecified (one shot), time reversed integer, intent(out) :: rc type (ESMF_Clock) :: clock type (ESMF_Alarm) :: alarm type (ESMF_Time) :: startTime, stopTime, ringTime - type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + type (ESMF_TimeInterval) :: timeStep - integer :: status, n, nrings=0 + integer :: status, n logical :: ringing, enabled, sticky + logical :: allCorrect - rc = ESMF_SUCCESS + rc = ESMF_FAILURE + allCorrect = .true. call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() @@ -2554,13 +2622,8 @@ subroutine ReverseAlarm_Test6(rc) call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=30,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - ! Test 6: c.t0 = a.t0, c.dt = 10 min a.dt = 12 min - print *, 'Test 6: c.t0 = a.t0, c.dt = 10 min a.dt = unspecified (one shot)' call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - call ESMF_TimeIntervalSet(ringTimeInterval,S=720, sN=0, sD=1,rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() - call ESMF_TimeIntervalSet(ringDuration,S=1, sN=0, sD=1,rc=status) clock = ESMF_ClockCreate(timeStep=timeStep,startTime=startTime,stopTime=stopTime,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() @@ -2568,24 +2631,36 @@ subroutine ReverseAlarm_Test6(rc) if(status /= ESMF_SUCCESS) call ESMF_Finalize() alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, enabled=.true., sticky=.false., name='alarm', rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - call ESMF_AlarmDebug(alarm,'test6',rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() + ! call ESMF_AlarmDebug(alarm,'test6',rc=status) + ! if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - if(ringing) nrings = nrings + 1 - print *, 'Test 6: ringing = ', ringing, trim(clockCurrTime(clock)), ' sticky = ', sticky + if (ringing) then + allCorrect = .false. + end if do n = 1, 6 call ESMF_ClockAdvance(clock,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - if(ringing) nrings = nrings + 1 - print *, ' Test 6: ringing = ', ringing, trim(clockCurrTime(clock)) + if (n == 3) then + ! Alarm should be ringing on the 3rd time step, when the clock time should match + ! the alarm's initial time + if (.not. ringing) then + allCorrect = .false. + end if + else + ! Alarm should NOT be ringing on other time steps + if (ringing) then + allCorrect = .false. + end if + end if enddo - rc = ESMF_FAILURE - if(nrings == 1) rc = ESMF_SUCCESS + if (allCorrect) then + rc = ESMF_SUCCESS + end if end subroutine !------------------------------------------------------------------------ @@ -2598,7 +2673,7 @@ subroutine ForwardReverseAlarm_Test1(rc) type (ESMF_Clock) :: clock type (ESMF_Alarm) :: alarm type (ESMF_Time) :: startTime, stopTime, ringTime - type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval integer :: status, n, nrings=0 logical :: ringing, enabled, sticky @@ -2623,8 +2698,8 @@ subroutine ForwardReverseAlarm_Test1(rc) if(status /= ESMF_SUCCESS) call ESMF_Finalize() alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, ringInterval=ringTimeInterval, enabled=.true., sticky=.false., name='alarm', rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - call ESMF_AlarmDebug(alarm,'test1',rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() + ! call ESMF_AlarmDebug(alarm,'test1',rc=status) + ! if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() @@ -2660,7 +2735,7 @@ subroutine ForwardReverseAlarm_Test2(rc) type (ESMF_Clock) :: clock type (ESMF_Alarm) :: alarm type (ESMF_Time) :: startTime, stopTime, ringTime - type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval integer :: status, n, nrings=0 logical :: ringing, enabled, sticky @@ -2685,8 +2760,8 @@ subroutine ForwardReverseAlarm_Test2(rc) if(status /= ESMF_SUCCESS) call ESMF_Finalize() alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, ringInterval=ringTimeInterval, enabled=.true., sticky=.false., name='alarm', rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - call ESMF_AlarmDebug(alarm,'test1',rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() + ! call ESMF_AlarmDebug(alarm,'test1',rc=status) + ! if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() @@ -2722,7 +2797,7 @@ subroutine ForwardReverseAlarm_Test3(rc) type (ESMF_Clock) :: clock type (ESMF_Alarm) :: alarm type (ESMF_Time) :: startTime, stopTime, ringTime - type (ESMF_TimeInterval) :: timeStep, ringTimeInterval, ringDuration + type (ESMF_TimeInterval) :: timeStep, ringTimeInterval integer :: status, n, nrings=0 logical :: ringing, enabled, sticky @@ -2747,8 +2822,8 @@ subroutine ForwardReverseAlarm_Test3(rc) if(status /= ESMF_SUCCESS) call ESMF_Finalize() alarm = ESMF_AlarmCreate(clock, ringTime=ringTime, ringInterval=ringTimeInterval, enabled=.true., sticky=.false., name='alarm', rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - call ESMF_AlarmDebug(alarm,'test1',rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() + ! call ESMF_AlarmDebug(alarm,'test1',rc=status) + ! if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() From fc8bbef68ca5264a8c72c4b7ff52f007f93d01ce Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Sat, 28 Dec 2024 06:52:29 -0700 Subject: [PATCH 19/32] Clean up ForwardReverseAlarm tests and make them more rigorous --- .../TimeMgr/tests/ESMF_AlarmUTest.F90 | 128 ++++++++++++------ 1 file changed, 86 insertions(+), 42 deletions(-) diff --git a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 index ed792116ff..efa26fa552 100644 --- a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 +++ b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 @@ -2667,6 +2667,7 @@ subroutine ReverseAlarm_Test6(rc) ! Forward and Reverse !------------------------------------------------------------------------ subroutine ForwardReverseAlarm_Test1(rc) + ! Test 1: c.t0 = a.t0, c.dt = a.dt = 10 min integer, intent(out) :: rc @@ -2675,11 +2676,13 @@ subroutine ForwardReverseAlarm_Test1(rc) type (ESMF_Time) :: startTime, stopTime, ringTime type (ESMF_TimeInterval) :: timeStep, ringTimeInterval - integer :: status, n, nrings=0 + integer :: status, n logical :: ringing, enabled, sticky + logical :: allCorrect + + rc = ESMF_FAILURE + allCorrect = .true. - rc = ESMF_SUCCESS - print *, 'Forward and Reverse Alarms Tests: ' call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) @@ -2687,8 +2690,6 @@ subroutine ForwardReverseAlarm_Test1(rc) call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - ! Test 1: c.t0 = a.t0, c.dt = a.dt = 10 min - print *, 'Test 1: c.t0 = a.t0, c.dt = a.dt = 10 min' call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_TimeIntervalSet(ringTimeInterval,S=600, sN=0, sD=1,rc=status) @@ -2703,15 +2704,17 @@ subroutine ForwardReverseAlarm_Test1(rc) call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - if(ringing) nrings = nrings + 1 - print *, 'Test 1: ringing = ', ringing, trim(clockCurrTime(clock)) + if (.not. ringing) then + allCorrect = .false. + end if do n = 1, 6 call ESMF_ClockAdvance(clock,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - print *, ' Test 1: ringing = ', ringing, trim(clockCurrTime(clock)) - if(ringing) nrings = nrings + 1 + if (.not. ringing) then + allCorrect = .false. + end if enddo call ESMF_ClockSet(clock, direction = ESMF_DIRECTION_REVERSE, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() @@ -2720,15 +2723,17 @@ subroutine ForwardReverseAlarm_Test1(rc) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - if(ringing) nrings = nrings + 1 - print *, ' Test 1: ringing = ', ringing, trim(clockCurrTime(clock)) + if (.not. ringing) then + allCorrect = .false. + end if enddo - rc = ESMF_FAILURE - print *, nrings - if(nrings == 13) rc = ESMF_SUCCESS + if (allCorrect) then + rc = ESMF_SUCCESS + end if end subroutine subroutine ForwardReverseAlarm_Test2(rc) + ! Test 2: c.t0 = a.t0, c.dt = 10 min, a.dt = 20 min integer, intent(out) :: rc @@ -2737,11 +2742,13 @@ subroutine ForwardReverseAlarm_Test2(rc) type (ESMF_Time) :: startTime, stopTime, ringTime type (ESMF_TimeInterval) :: timeStep, ringTimeInterval - integer :: status, n, nrings=0 + integer :: status, n logical :: ringing, enabled, sticky + logical :: allCorrect + + rc = ESMF_FAILURE + allCorrect = .true. - rc = ESMF_SUCCESS - print *, 'Forward and Reverse Alarms Tests: ' call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) @@ -2749,8 +2756,6 @@ subroutine ForwardReverseAlarm_Test2(rc) call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - ! Test 2: c.t0 = a.t0, c.dt = a.dt = 10 min - print *, 'Test 2: c.t0 = a.t0, c.dt = a.dt = 20 min' call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_TimeIntervalSet(ringTimeInterval,S=1200, sN=0, sD=1,rc=status) @@ -2765,15 +2770,25 @@ subroutine ForwardReverseAlarm_Test2(rc) call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - if(ringing) nrings = nrings + 1 - print *, 'Test 2: ringing = ', ringing, trim(clockCurrTime(clock)) + if (.not. ringing) then + allCorrect = .false. + end if do n = 1, 6 call ESMF_ClockAdvance(clock,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - print *, ' Test 2: ringing = ', ringing, trim(clockCurrTime(clock)) - if(ringing) nrings = nrings + 1 + if (modulo(n,2) == 0) then + ! Alarm should be ringing on even time steps + if (.not. ringing) then + allCorrect = .false. + end if + else + ! Alarm should NOT be ringing on odd time steps + if (ringing) then + allCorrect = .false. + end if + end if enddo call ESMF_ClockSet(clock, direction = ESMF_DIRECTION_REVERSE, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() @@ -2782,15 +2797,25 @@ subroutine ForwardReverseAlarm_Test2(rc) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - if(ringing) nrings = nrings + 1 - print *, ' Test 2: ringing = ', ringing, trim(clockCurrTime(clock)) + if (modulo(n,2) == 0) then + ! Alarm should be ringing on even time steps + if (.not. ringing) then + allCorrect = .false. + end if + else + ! Alarm should NOT be ringing on odd time steps + if (ringing) then + allCorrect = .false. + end if + end if enddo - rc = ESMF_FAILURE - print *, nrings - if(nrings == 7) rc = ESMF_SUCCESS + if (allCorrect) then + rc = ESMF_SUCCESS + end if end subroutine subroutine ForwardReverseAlarm_Test3(rc) + ! Test 3: c.t0 = a.t0, c.dt = 10 min, a.dt = 12 min integer, intent(out) :: rc @@ -2799,11 +2824,13 @@ subroutine ForwardReverseAlarm_Test3(rc) type (ESMF_Time) :: startTime, stopTime, ringTime type (ESMF_TimeInterval) :: timeStep, ringTimeInterval - integer :: status, n, nrings=0 + integer :: status, n logical :: ringing, enabled, sticky + logical :: allCorrect + + rc = ESMF_FAILURE + allCorrect = .true. - rc = ESMF_SUCCESS - print *, 'Forward and Reverse Alarms Tests: ' call ESMF_TimeSet(startTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_TimeSet(stopTime,yy=1,mm=1,dd=1,h=1,m=0,s=0,rc=status) @@ -2811,8 +2838,6 @@ subroutine ForwardReverseAlarm_Test3(rc) call ESMF_TimeSet(ringTime,yy=1,mm=1,dd=1,h=0,m=0,s=0,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - ! Test 3: c.t0 = a.t0, c.dt = a.dt = 10 min - print *, 'Test 3: c.t0 = a.t0, c.dt = a.dt = 12 min' call ESMF_TimeIntervalSet(timeStep,S=600, sN=0, sD=1,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_TimeIntervalSet(ringTimeInterval,S=720, sN=0, sD=1,rc=status) @@ -2827,15 +2852,25 @@ subroutine ForwardReverseAlarm_Test3(rc) call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - if(ringing) nrings = nrings + 1 - print *, 'Test 3: ringing = ', ringing, trim(clockCurrTime(clock)) + if (.not. ringing) then + allCorrect = .false. + end if do n = 1, 6 call ESMF_ClockAdvance(clock,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - print *, ' Test 3: ringing = ', ringing, trim(clockCurrTime(clock)) - if(ringing) nrings = nrings + 1 + if (n == 6) then + ! Alarm should be ringing on the 6th time step, when alarm dt aligns with clock dt + if (.not. ringing) then + allCorrect = .false. + end if + else + ! Alarm should NOT be ringing on other time steps + if (ringing) then + allCorrect = .false. + end if + end if enddo call ESMF_ClockSet(clock, direction = ESMF_DIRECTION_REVERSE, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() @@ -2844,12 +2879,21 @@ subroutine ForwardReverseAlarm_Test3(rc) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - if(ringing) nrings = nrings + 1 - print *, ' Test 3: ringing = ', ringing, trim(clockCurrTime(clock)) + if (n == 6) then + ! Alarm should be ringing on the 6th time step, when alarm dt aligns with clock dt + if (.not. ringing) then + allCorrect = .false. + end if + else + ! Alarm should NOT be ringing on other time steps + if (ringing) then + allCorrect = .false. + end if + end if enddo - rc = ESMF_FAILURE - print *, nrings - if(nrings == 3) rc = ESMF_SUCCESS + if (allCorrect) then + rc = ESMF_SUCCESS + end if end subroutine end program ESMF_AlarmTest From 41c61d115b007dd350d7729cafacfe08a4fc31e9 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Sat, 28 Dec 2024 07:23:08 -0700 Subject: [PATCH 20/32] Clean up Test_ClockSet and call it with both forward and reverse clocks --- .../TimeMgr/tests/ESMF_AlarmUTest.F90 | 61 ++++++++----------- 1 file changed, 24 insertions(+), 37 deletions(-) diff --git a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 index efa26fa552..3d22e2e08f 100644 --- a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 +++ b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 @@ -1192,14 +1192,21 @@ program ESMF_AlarmTest !EX_UTest write(failMsg, *) " Alarms with ClockSet... " - write(name, *) "Test ClockSet after alarm attached to clock " - rc = ESMF_SUCCESS - testPass = .true. - call Test_ClockSet(testPass, rc) + write(name, *) "Test ClockSet after alarm attached to clock, forward time " + call Test_ClockSet(doReverse=.false., testPass=testPass, rc=rc) if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. if (.not. testPass) print *, 'bad return codes discovered' call ESMF_Test (testPass, name, failMsg, result, ESMF_SRCLINE) + ! ---------------------------------------------------------------------------- + + !EX_UTest + write(failMsg, *) " Alarms with ClockSet... " + write(name, *) "Test ClockSet after alarm attached to clock, reverse time " + call Test_ClockSet(doReverse=.true., testPass=testPass, rc=rc) + if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. + if (.not. testPass) print *, 'bad return codes discovered' + call ESMF_Test (testPass, name, failMsg, result, ESMF_SRCLINE) ! ---------------------------------------------------------------------------- @@ -1699,21 +1706,24 @@ subroutine verify_(rc) end if end subroutine verify_ -subroutine Test_ClockSet(testPass, rc) +subroutine Test_ClockSet(doReverse, testPass, rc) + ! Test ClockSet after an alarm is attached to the clock #define CONTEXT line=__LINE__,file=__FILE__ #define CHECKRC if(ESMF_LogFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,CONTEXT,rcToReturn=rc))then;write(0,*)'app abort: ',__FILE__,__LINE__;return;endif + logical, intent(in) :: doReverse ! whether to set up the clock with reverse direction logical, intent(out) :: testPass + integer, intent(out) :: rc integer, parameter :: r8 = SELECTED_REAL_KIND(12) ! real r8 - integer :: rc type(ESMF_Clock) :: clock type(ESMF_Alarm) :: alarm type(ESMF_TimeInterval) :: esmf_ival type(ESMF_Time) :: time, initial, finish, ring_time real(kind=r8) :: secs - logical :: reverse_clock, sticky_alarm + logical :: sticky_alarm rc = ESMF_SUCCESS + testPass = .false. call ESMF_CalendarSetDefault ( ESMF_CALKIND_GREGORIAN, rc=rc) CHECKRC @@ -1725,15 +1735,11 @@ subroutine Test_ClockSet(testPass, rc) CHECKRC initial = time + esmf_ival - call ESMF_TimePrint(initial, options="string", rc=rc) - CHECKRC secs = 6000 call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) CHECKRC finish = time + 2*esmf_ival - call ESMF_TimePrint(finish, options="string", rc=rc) - CHECKRC secs = 60 call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) @@ -1744,44 +1750,25 @@ subroutine Test_ClockSet(testPass, rc) ,refTime=time, rc=rc ) CHECKRC - call ESMF_ClockSet(clock,direction=ESMF_DIRECTION_REVERSE, rc=rc) - CHECKRC - - reverse_clock = ESMF_ClockIsReverse(clock, rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) - sticky_alarm = .not.reverse_clock - - write(0,'("reverse =",x,l)') reverse_clock - write(0,'("sticky =",x,l)') sticky_alarm + if (doReverse) then + call ESMF_ClockSet(clock,direction=ESMF_DIRECTION_REVERSE, rc=rc) + CHECKRC + sticky_alarm = .false. + else + sticky_alarm = .true. + end if secs = 3000 call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) CHECKRC ring_time = initial + 2*esmf_ival - print *, 'Before Alarm Create ringTime: ' - call ESMF_TimePrint(ring_time, options="string", rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) -#if 1 alarm = ESMF_AlarmCreate(clock, ringTime=ring_time, sticky=sticky_alarm, & rc=rc) CHECKRC -#else - alarm = ESMF_AlarmCreate(clock, ringTime=ring_time, sticky=.false., & - rc=rc) - CHECKRC -#endif - - call ESMF_TimePrint(ring_time, options="string", rc=rc) - CHECKRC - print *, 'After Alarm Create ringTime: ' - call ESMF_TimePrint(ring_time, options="string", rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) call ESMF_ClockSet(clock, stopTime=ring_time, rc=rc) CHECKRC - call ESMF_alarmPrint(alarm,options='sticky') - testPass = .true. ! Because the C++ runtime failure cannot be caught reliably, set this to false. #undef CONTEXT From 635c111297a4ac3c45615d0405c32e30e888670f Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Sat, 28 Dec 2024 07:30:17 -0700 Subject: [PATCH 21/32] Remove some "#if 1" conditionals --- src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 index 3d22e2e08f..79061ee555 100644 --- a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 +++ b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 @@ -1259,7 +1259,6 @@ program ESMF_AlarmTest ! ---------------------------------------------------------------------------- -#if 1 !EX_UTest write(failMsg, *) " Alarms with getPrevRingTime... " write(name, *) "Test getPrevRingTime... after alarm attached to clock " @@ -1269,7 +1268,6 @@ program ESMF_AlarmTest if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. if (.not. testPass) print *, 'bad return codes discovered' call ESMF_Test (testPass, name, failMsg, result, ESMF_SRCLINE) -#endif ! ---------------------------------------------------------------------------- ! ---------------------------------------------------------------------------- @@ -1284,7 +1282,6 @@ program ESMF_AlarmTest ! finalize ESMF framework call ESMF_TestEnd(ESMF_SRCLINE) -#if 1 contains subroutine test_reverseAlarms(testPass, rc) @@ -1868,8 +1865,6 @@ subroutine Test_GetPrevRingTime(testPass, rc) end subroutine Test_GetPrevRingTime -#endif - character*64 function clockCurrTime(clock) type(ESMF_Clock) :: clock type(ESMF_Time ) :: time From ecec44449bb78729fc504ec123680b57c1a4da61 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Sun, 29 Dec 2024 08:26:30 -0700 Subject: [PATCH 22/32] Improve rigor of Test_ReverseAlarms --- .../TimeMgr/tests/ESMF_AlarmUTest.F90 | 218 +++++++++++------- 1 file changed, 139 insertions(+), 79 deletions(-) diff --git a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 index 79061ee555..9025ef5199 100644 --- a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 +++ b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 @@ -1214,8 +1214,6 @@ program ESMF_AlarmTest ! The following tests are from Ben@NASA's support ticket 3614994 write(failMsg, *) " Alarms did not rewind correct number of times " write(name, *) "Test multiple alarms rewind correct number of times " - rc = ESMF_SUCCESS - testPass = .true. call Test_ReverseAlarms(testPass, rc) if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. if (.not. testPass) print *, 'bad return codes discovered' @@ -1284,11 +1282,12 @@ program ESMF_AlarmTest contains - subroutine test_reverseAlarms(testPass, rc) + subroutine test_ReverseAlarms(testPass, rc) implicit none logical, intent(out) :: testPass - integer :: status,rc + integer, intent(out) :: rc + integer :: status type(ESMF_TimeInterval) :: dt type(ESMF_Time) :: start_time, clock_start, clock_end @@ -1299,14 +1298,16 @@ subroutine test_reverseAlarms(testPass, rc) type(ESMF_TimeInterval) :: tint type(ESMF_Alarm) :: esmfalarm, firstalarm - integer :: i,nstep, nrings1, nrings2 + integer :: i,nstep type(ESMF_Time) :: time - character(len=10) :: iam='test_clock' - logical :: esmf_ring - integer :: nalarms, n_rings=0 + logical :: esmfalarm_ring, firstalarm_ring + logical :: allCorrect + rc = ESMF_SUCCESS testPass = .false. + allCorrect = .true. + call ESMF_CalendarSetDefault ( ESMF_CALKIND_GREGORIAN, rc=status ) call verify_(status) call ESMF_TimeSet(clock_start,yy=2000,mm=1,dd=1,h=21,m=0,s=0,rc=status) @@ -1322,97 +1323,157 @@ subroutine test_reverseAlarms(testPass, rc) call ESMF_ClockSet(clock,currTime=start_time,rc=status) call verify_(status) - call ESMF_ClockGet(clock,currtime=start_time,rc=status) - if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_TimeIntervalSet(tint,h=2,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() firstalarm = ESMF_AlarmCreate(clock=clock,ringInterval=tint,ringTime=start_time,sticky=.false.,name="alarm1",rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() + firstalarm_ring = ESMF_AlarmIsRinging(firstalarm,rc=status) + call verify_(status) + if (.not. firstalarm_ring) then + allCorrect = .false. + end if - nstep=47 - call ESMF_ClockGet(clock,currtime=start_time,alarmCount=nalarms,rc=status) - !write(*,*) "alarms already in clock: ",nalarms + call ESMF_ClockGet(clock,currtime=start_time,rc=status) call verify_(status) call ESMF_TimeIntervalSet(tint,h=1,rc=status) call verify_(status) esmfalarm = ESMF_AlarmCreate(clock=clock,ringInterval=tint,ringTime=start_time,sticky=.false.,name="alarm2",rc=status) - nrings1 = 0 - nrings2 = 0 + call verify_(status) + esmfalarm_ring = ESMF_AlarmIsRinging(esmfalarm,rc=status) + call verify_(status) + if (.not. esmfalarm_ring) then + allCorrect = .false. + end if + nstep=47 do i=1,nstep - !call ESMF_ClockDebug(clock, 'forward clock', rc=status) - !call verify_(status) - !call ESMF_AlarmDebug(esmfalarm, 'forward esmfalarm', rc=status) - !call verify_(status) - call ESMF_ClockGet(clock,currTime=time) - esmf_ring = ESMF_AlarmIsRinging(esmfalarm,rc=status) - call verify_(status) - if ( esmf_ring) then - write(*,*)'ringing' - call ESMF_TimePrint(time,options='string') - nrings2=nrings2 + 1 - end if - call ESMF_ClockAdvance(clock) + call ESMF_ClockAdvance(clock,rc=status) + call verify_(status) + !call ESMF_ClockDebug(clock, 'forward clock', rc=status) + !call verify_(status) + !call ESMF_AlarmDebug(esmfalarm, 'forward esmfalarm', rc=status) + !call verify_(status) + + esmfalarm_ring = ESMF_AlarmIsRinging(esmfalarm,rc=status) + call verify_(status) + if (modulo(i,4) == 0) then + ! Time step of 15 minutes, alarm rings every hour, so alarm should ring every 4th time step + if (.not. esmfalarm_ring) then + allCorrect = .false. + end if + else + if (esmfalarm_ring) then + allCorrect = .false. + end if + end if + + firstalarm_ring = ESMF_AlarmIsRinging(firstalarm,rc=status) + call verify_(status) + if (modulo(i,8) == 0) then + ! Time step of 15 minutes, alarm rings every two hours, so alarm should ring every 8th time step + if (.not. firstalarm_ring) then + allCorrect = .false. + end if + else + if (firstalarm_ring) then + allCorrect = .false. + end if + end if enddo - if(nrings2 == 12) then - testPass = .true. ! ringerIV = 1h, timeST=15min, 48/4=12 - else - return - endif - testPass = .false. + call ESMF_ClockSet(clock, direction=ESMF_DIRECTION_REVERSE, rc=status) call verify_(status) - !write(*,*)"*************** start rewind *********************" i = 0 do - i = i + 1 - write(*,*) 'Rewind step: ', i - call ESMF_ClockAdvance(clock,rc=status) - call verify_(status) - !call ESMF_ClockDebug(clock, 'reverse clock', rc=status) - !call verify_(status) - !call ESMF_AlarmDebug(esmfalarm, 'reverse esmfalarm', rc=status) - !call verify_(status) - call ESMF_ClockGet(clock,currTime=time) - if (ESMF_AlarmIsRinging(esmfalarm)) then - write(*,*)'rewinding one step ',ESMF_AlarmIsRinging(esmfalarm) - n_rings = n_rings + 1 - call ESMF_TimePrint(time,options='string') - end if - - if (time == start_time) exit + i = i + 1 + call ESMF_ClockAdvance(clock,rc=status) + call verify_(status) + !call ESMF_ClockDebug(clock, 'reverse clock', rc=status) + !call verify_(status) + !call ESMF_AlarmDebug(esmfalarm, 'reverse esmfalarm', rc=status) + !call verify_(status) + + esmfalarm_ring = ESMF_AlarmIsRinging(esmfalarm,rc=status) + call verify_(status) + if (modulo((i-3),4) == 0) then + ! Time step of 15 minutes, with time starting at 45 minutes past the hour, alarm + ! rings every hour, so alarm should ring every 4th time step starting with i==3 + if (.not. esmfalarm_ring) then + allCorrect = .false. + end if + else + if (esmfalarm_ring) then + allCorrect = .false. + end if + end if + + firstalarm_ring = ESMF_AlarmIsRinging(firstalarm,rc=status) + call verify_(status) + if (modulo((i-7),8) == 0) then + ! Time step of 15 minutes, with time starting at 45 minutes past an odd-numbered + ! hour, alarm rings every two hours, so alarm should ring every 8th time step + ! starting with i==7 + if (.not. firstalarm_ring) then + allCorrect = .false. + end if + else + if (firstalarm_ring) then + allCorrect = .false. + end if + end if + + call ESMF_ClockGet(clock,currTime=time) + if (time == start_time) exit enddo - if(n_rings == 12) then - testPass = .true. ! ringerIV = 1h, timeST=15min, 48/4=12 - else - return - endif - testPass = .false. + call ESMF_ClockSet(clock, direction=ESMF_DIRECTION_FORWARD, rc=status) call verify_(status) - write(*,*)"*************** end rewind *********************" do i=1,nstep*2 - !call ESMF_ClockDebug(clock, 'forward clock again', rc=status) - !call verify_(status) - !call ESMF_AlarmDebug(esmfalarm, 'forward esmfalarm again', rc=status) - !call verify_(status) - call ESMF_ClockGet(clock,currTime=time) - esmf_ring = ESMF_AlarmIsRinging(esmfalarm,rc=status) - call verify_(status) - if ( esmf_ring ) then - write(*,*)'ringing' - call ESMF_TimePrint(time,options='string') - end if - call ESMF_ClockAdvance(clock) + call ESMF_ClockAdvance(clock,rc=status) + call verify_(status) + !call ESMF_ClockDebug(clock, 'forward clock again', rc=status) + !call verify_(status) + !call ESMF_AlarmDebug(esmfalarm, 'forward esmfalarm again', rc=status) + !call verify_(status) + + esmfalarm_ring = ESMF_AlarmIsRinging(esmfalarm,rc=status) + call verify_(status) + if (modulo(i,4) == 0) then + ! Time step of 15 minutes, alarm rings every hour, so alarm should ring every 4th time step + if (.not. esmfalarm_ring) then + allCorrect = .false. + end if + else + if (esmfalarm_ring) then + allCorrect = .false. + end if + end if + + firstalarm_ring = ESMF_AlarmIsRinging(firstalarm,rc=status) + call verify_(status) + if (modulo(i,8) == 0) then + ! Time step of 15 minutes, alarm rings every two hours, so alarm should ring every 8th time step + if (.not. firstalarm_ring) then + allCorrect = .false. + end if + else + if (firstalarm_ring) then + allCorrect = .false. + end if + end if enddo - if(n_rings == 12) testPass = .true. - call ESMF_AlarmDestroy(esmfalarm, rc=status) - call verify_(status) - call ESMF_AlarmDestroy(firstalarm, rc=status) - call verify_(status) - call ESMF_ClockDestroy(clock, rc=status) - call verify_(status) - + call ESMF_AlarmDestroy(esmfalarm, rc=status) + call verify_(status) + call ESMF_AlarmDestroy(firstalarm, rc=status) + call verify_(status) + call ESMF_ClockDestroy(clock, rc=status) + call verify_(status) + + if (allCorrect) then + testPass = .true. + else + testPass = .false. + end if end subroutine Test_ReverseAlarms subroutine Test_AlarmHang(testPass, rc) @@ -1431,7 +1492,6 @@ subroutine Test_AlarmHang(testPass, rc) type(ESMF_Time) :: time type(ESMF_Alarm) :: esmfalarm type(ESMF_Alarm) :: testalarm - character(len=10) :: iam='test_clock' logical :: esmf_ring integer :: nalarms From f601b7050dcff3725eee5d4cbaba96bd5209f0df Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Thu, 2 Jan 2025 15:40:25 -0700 Subject: [PATCH 23/32] Clean up Test_AlarmHang and make it more robust --- .../TimeMgr/tests/ESMF_AlarmUTest.F90 | 140 ++++++++++++------ 1 file changed, 92 insertions(+), 48 deletions(-) diff --git a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 index 9025ef5199..717fdb51f8 100644 --- a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 +++ b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 @@ -1224,8 +1224,6 @@ program ESMF_AlarmTest !EX_UTest write(failMsg, *) " Alarms hang... " write(name, *) "Test multiple alarms replay without hanging " - rc = ESMF_SUCCESS - testPass = .true. call Test_AlarmHang(testPass, rc) if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. if (.not. testPass) print *, 'bad return codes discovered' @@ -1292,8 +1290,6 @@ subroutine test_ReverseAlarms(testPass, rc) type(ESMF_TimeInterval) :: dt type(ESMF_Time) :: start_time, clock_start, clock_end type(ESMF_Clock) :: clock - character(len=5) :: add_2nd - integer :: nargs type(ESMF_TimeInterval) :: tint type(ESMF_Alarm) :: esmfalarm, firstalarm @@ -1478,24 +1474,26 @@ end subroutine Test_ReverseAlarms subroutine Test_AlarmHang(testPass, rc) logical, intent(out) :: testPass - integer :: status,rc + integer, intent(out) :: rc + + integer :: status type(ESMF_TimeInterval) :: dt type(ESMF_Time) :: start_time, clock_start, clock_end type(ESMF_Clock) :: clock - character(len=5) :: add_2nd - integer :: nargs - + integer :: i,nstep type(ESMF_TimeInterval) :: tint type(ESMF_Time) :: time type(ESMF_Alarm) :: esmfalarm type(ESMF_Alarm) :: testalarm - logical :: esmf_ring - integer :: nalarms + logical :: esmfalarm_ring, testalarm_ring + logical :: allCorrect + rc = ESMF_SUCCESS testPass = .false. + allCorrect = .true. call ESMF_CalendarSetDefault ( ESMF_CALKIND_GREGORIAN, rc=status ) call verify_(status) @@ -1513,9 +1511,6 @@ subroutine Test_AlarmHang(testPass, rc) call verify_(status) nstep = 12 - call ESMF_ClockGet(clock,currtime=start_time,alarmCount=nalarms,rc=status) - !write(*,*) "alarms already in clock: ",nalarms - call verify_(status) call ESMF_TimeIntervalSet(tint,h=1,rc=status) call verify_(status) esmfalarm = ESMF_AlarmCreate(clock=clock,ringInterval=tint,ringTime=start_time,sticky=.false.,name="alarm2",rc=status) @@ -1526,50 +1521,95 @@ subroutine Test_AlarmHang(testPass, rc) call ESMF_AlarmRingerOff(testalarm,rc=status) call verify_(status) do i=1,nstep - call ESMF_AlarmRingerOn(testalarm,rc=status) - call verify_(status) - call ESMF_ClockGet(clock,currTime=time) - esmf_ring = ESMF_AlarmIsRinging(esmfalarm,rc=status) - call verify_(status) - if ( esmf_ring) then - !write(*,*)'ringing: esmfalarm' - call ESMF_TimePrint(time,options='string') - end if - call ESMF_ClockAdvance(clock) + call ESMF_AlarmRingerOn(testalarm,rc=status) + call verify_(status) + esmfalarm_ring = ESMF_AlarmIsRinging(esmfalarm,rc=status) + call verify_(status) + if (modulo((i-1),4) == 0) then + if (.not. esmfalarm_ring) then + allCorrect = .false. + end if + else + if (esmfalarm_ring) then + allCorrect = .false. + end if + end if + testalarm_ring = ESMF_AlarmIsRinging(testalarm,rc=status) + call verify_(status) + if (.not. testalarm_ring) then + allCorrect = .false. + end if + call ESMF_ClockAdvance(clock,rc=status) + call verify_(status) enddo + call ESMF_ClockSet(clock, direction=ESMF_DIRECTION_REVERSE, rc=status) call verify_(status) call ESMF_AlarmRingerOff(testalarm,rc=status) call verify_(status) - !write(*,*)"*************** start rewind *********************" + i = 0 do - call ESMF_ClockAdvance(clock,rc=status) - call verify_(status) - call ESMF_ClockGet(clock,currTime=time) - if (ESMF_AlarmIsRinging(esmfalarm)) then - !write(*,*)'rewinding one step: esmfalarm ',ESMF_AlarmIsRinging(esmfalarm) - call ESMF_TimePrint(time,options='string') - end if - - if (ESMF_AlarmIsRinging(esmfalarm)) then - write(*,*)'rewinding one step: testalarm ',ESMF_AlarmIsRinging(testalarm) - call ESMF_TimePrint(time,options='string') - end if - - if (time == start_time) exit + i = i + 1 + call ESMF_ClockAdvance(clock,rc=status) + call verify_(status) + esmfalarm_ring = ESMF_AlarmIsRinging(esmfalarm,rc=status) + call verify_(status) + if (modulo(i,4) == 0) then + if (.not. esmfalarm_ring) then + allCorrect = .false. + end if + else + if (esmfalarm_ring) then + allCorrect = .false. + end if + end if + testalarm_ring = ESMF_AlarmIsRinging(testalarm,rc=status) + call verify_(status) + call ESMF_ClockGet(clock,currTime=time,rc=status) + call verify_(status) + if (time == start_time & + ! Reversing the clock leads to a shift by one time step in the alarm time, so + ! we also expect it to ring at (start_time + dt) (see also discussion here: + ! https://github.com/esmf-org/esmf/pull/340#discussion_r1900300522) + .or. time == (start_time + dt) & + ! FIXME:(wjs, 2025-01-02) Due to what may be a bug, the clock also currently + ! rings at start_time + 2*dt, because the ring time is adjusted by an + ! additional dt when calling ESMF_AlarmRingerOff after setting the clock's + ! direction to reverse (see + ! https://github.com/esmf-org/esmf/pull/340#issuecomment-2566736806) + .or. time == (start_time + 2*dt)) then + if (.not. testalarm_ring) then + allCorrect = .false. + end if + else + if (testalarm_ring) then + allCorrect = .false. + end if + end if + if (time == start_time) exit enddo + call ESMF_ClockSet(clock, direction=ESMF_DIRECTION_FORWARD, rc=status) call verify_(status) - !write(*,*)"*************** end rewind *********************" do i=1,nstep*2 - call ESMF_ClockGet(clock,currTime=time) - esmf_ring = ESMF_AlarmIsRinging(esmfalarm,rc=status) - call verify_(status) - if ( esmf_ring ) then - !write(*,*)'ringing: esmfalarm' - call ESMF_TimePrint(time,options='string') - end if - call ESMF_ClockAdvance(clock) + esmfalarm_ring = ESMF_AlarmIsRinging(esmfalarm,rc=status) + call verify_(status) + if (modulo((i-1),4) == 0) then + if (.not. esmfalarm_ring) then + allCorrect = .false. + end if + else + if (esmfalarm_ring) then + allCorrect = .false. + end if + end if + testalarm_ring = ESMF_AlarmIsRinging(testalarm,rc=status) + call verify_(status) + if (.not. testalarm_ring) then + allCorrect = .false. + end if + call ESMF_ClockAdvance(clock,rc=status) + call verify_(status) enddo call ESMF_AlarmDestroy(esmfalarm, rc=status) @@ -1579,7 +1619,11 @@ subroutine Test_AlarmHang(testPass, rc) call ESMF_ClockDestroy(clock, rc=status) call verify_(status) - testPass = .true. + if (allCorrect) then + testPass = .true. + else + testPass = .false. + end if end subroutine Test_AlarmHang From 7a45c0d039a55a5bed2c990f1211ef27aa225ea7 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Thu, 2 Jan 2025 16:52:42 -0700 Subject: [PATCH 24/32] Clean up Test_AlarmAdvRewind and make it actually test things rigorously --- .../TimeMgr/tests/ESMF_AlarmUTest.F90 | 240 ++++++++++-------- 1 file changed, 134 insertions(+), 106 deletions(-) diff --git a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 index 717fdb51f8..89fe7ce465 100644 --- a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 +++ b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 @@ -1234,8 +1234,6 @@ program ESMF_AlarmTest !EX_UTest write(failMsg, *) " Alarms with ring intervals equal to clock interval, incorrect behavior " write(name, *) "Test running an alarms forward-reverse-forward with ring interval equal to clock interval " - rc = ESMF_SUCCESS - testPass = .true. call Test_AlarmAdvRewind(testPass, rc) if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. if (.not. testPass) print *, 'bad return codes discovered' @@ -1629,111 +1627,141 @@ end subroutine Test_AlarmHang subroutine Test_AlarmAdvRewind(testPass, rc) logical, intent(out) :: testPass - integer :: rc + integer, intent(out) :: rc - type(ESMF_TimeInterval) :: dt - type(ESMF_Time) :: start_time, clock_start, clock_end - type(ESMF_Clock) :: clock - - type(ESMF_TimeInterval) :: tint - - integer :: status,i,j,nstep, nrings(2) - - logical :: esmf_ring - character(len=ESMF_MAXSTR) :: alarm_name - integer :: nalarms - type(ESMF_Alarm), allocatable :: alarm_list(:) - type(ESMF_Time) :: time - type(ESMF_Alarm) :: esmfalarm - type(ESMF_CalKind_Flag) :: calkindflag - - rc = ESMF_SUCCESS - - !call ESMF_CalendarGet(calkindflag=calkindflag, rc=status) - !call verify_(status) - call ESMF_CalendarSetDefault ( ESMF_CALKIND_GREGORIAN, rc=status ) - call verify_(status) - call ESMF_TimeSet(clock_start,yy=2000,mm=1,dd=1,h=21,m=0,s=0,rc=status) - call verify_(status) - call ESMF_TimeSet(clock_end,yy=2000,mm=12,dd=1,h=21,m=0,s=0,rc=status) - call verify_(status) - call ESMF_TimeSet(start_time,yy=2000,mm=10,dd=1,h=21,m=0,s=0,rc=status) - call verify_(status) - call ESMF_TimeIntervalSet(dt,S=900, sN=0, sD=1,rc=status) - call verify_(status) - clock= ESMF_ClockCreate(timeStep=dt,startTime=clock_start,stopTime=clock_end,rc=status) - call verify_(status) - call ESMF_ClockSet(clock,currTime=start_time,rc=status) - call verify_(status) - - ! fails if s=900 - call ESMF_TimeIntervalSet(tint,s=900) - esmfalarm = ESMF_AlarmCreate(clock=clock,ringInterval=tint,ringTime=start_time,sticky=.false.,name='alarm_900',rc=status) - call verify_(status) - ! works if s=1800 - call ESMF_TimeIntervalSet(tint,s=1800) - esmfalarm = ESMF_AlarmCreate(clock=clock,ringInterval=tint,ringTime=start_time,sticky=.false.,name='alarm_1800',rc=status) - call verify_(status) - - - nstep=12 - nrings=0 - call ESMF_ClockGet(clock,currtime=start_time,alarmCount=nalarms,rc=status) - allocate(alarm_list(nalarms)) - call ESMF_ClockGetAlarmList(clock, alarmListFlag=ESMF_ALARMLIST_ALL, alarmList=alarm_list) - - do i=1,nstep - call ESMF_ClockGet(clock,currTime=time) - do j = 1,nalarms - call ESMF_AlarmGet(alarm_list(j),name=alarm_name) - esmf_ring = ESMF_AlarmIsRinging(alarm_list(j),rc=status) - call verify_(status) - if ( esmf_ring) then - nrings(j) = nrings(j) + 1 - write(*,*)trim(alarm_name)//' is ringing' - call ESMF_TimePrint(time,options='string') - end if - end do - call ESMF_ClockAdvance(clock) - enddo - call ESMF_ClockSet(clock, direction=ESMF_DIRECTION_REVERSE, rc=status) - call verify_(status) - write(*,*)"*************** start rewind *********************" - nrings=0 - do - call ESMF_ClockAdvance(clock,rc=status) - call verify_(status) - call ESMF_ClockGet(clock,currTime=time) - do j=1,nalarms - call ESMF_AlarmGet(alarm_list(j),name=alarm_name) - if (ESMF_AlarmIsRinging(alarm_list(j))) then - nrings(j) = nrings(j) + 1 - write(*,*)trim(alarm_name)//' is ringing' - call ESMF_TimePrint(time,options='string') - end if - end do - - if (time == start_time) exit - enddo - call ESMF_ClockSet(clock, direction=ESMF_DIRECTION_FORWARD, rc=status) - call verify_(status) - write(*,*)"*************** end rewind *********************" - nrings=0 - do i=1,nstep*2 - call ESMF_ClockGet(clock,currTime=time) - do j = 1,nalarms - call ESMF_AlarmGet(alarm_list(j),name=alarm_name) - esmf_ring = ESMF_AlarmIsRinging(alarm_list(j),rc=status) - call verify_(status) - if ( esmf_ring) then - nrings(j) = nrings(j) + 1 - write(*,*)trim(alarm_name)//' is ringing' - call ESMF_TimePrint(time,options='string') - end if - end do - call ESMF_ClockAdvance(clock) - enddo - + type(ESMF_TimeInterval) :: dt + type(ESMF_Time) :: start_time, clock_start, clock_end + type(ESMF_Clock) :: clock + + type(ESMF_TimeInterval) :: tint + + integer :: status,i,j,nstep + + character(len=ESMF_MAXSTR) :: alarm_name + type(ESMF_Time) :: time + type(ESMF_Alarm) :: esmfalarm900, esmfalarm1800 + logical :: esmfalarm900_ring, esmfalarm1800_ring + logical :: allCorrect + + rc = ESMF_SUCCESS + testPass = .false. + allCorrect = .true. + + call ESMF_CalendarSetDefault ( ESMF_CALKIND_GREGORIAN, rc=status ) + call verify_(status) + call ESMF_TimeSet(clock_start,yy=2000,mm=1,dd=1,h=21,m=0,s=0,rc=status) + call verify_(status) + call ESMF_TimeSet(clock_end,yy=2000,mm=12,dd=1,h=21,m=0,s=0,rc=status) + call verify_(status) + call ESMF_TimeSet(start_time,yy=2000,mm=10,dd=1,h=21,m=0,s=0,rc=status) + call verify_(status) + call ESMF_TimeIntervalSet(dt,S=900, sN=0, sD=1,rc=status) + call verify_(status) + clock= ESMF_ClockCreate(timeStep=dt,startTime=clock_start,stopTime=clock_end,rc=status) + call verify_(status) + call ESMF_ClockSet(clock,currTime=start_time,rc=status) + call verify_(status) + + call ESMF_TimeIntervalSet(tint,s=900) + esmfalarm900 = ESMF_AlarmCreate(clock=clock,ringInterval=tint,ringTime=start_time,sticky=.false.,name='alarm_900',rc=status) + call verify_(status) + call ESMF_TimeIntervalSet(tint,s=1800) + esmfalarm1800 = ESMF_AlarmCreate(clock=clock,ringInterval=tint,ringTime=start_time,sticky=.false.,name='alarm_1800',rc=status) + call verify_(status) + + esmfalarm900_ring = ESMF_AlarmIsRinging(esmfalarm900, rc=status) + call verify_(status) + if (.not. esmfalarm900_ring) then + allCorrect = .false. + end if + esmfalarm1800_ring = ESMF_AlarmIsRinging(esmfalarm1800, rc=status) + call verify_(status) + if (.not. esmfalarm1800_ring) then + allCorrect = .false. + end if + + nstep=12 + do i=1,nstep + call ESMF_ClockAdvance(clock) + + esmfalarm900_ring = ESMF_AlarmIsRinging(esmfalarm900, rc=status) + call verify_(status) + if (.not. esmfalarm900_ring) then + allCorrect = .false. + end if + + esmfalarm1800_ring = ESMF_AlarmIsRinging(esmfalarm1800, rc=status) + call verify_(status) + if (modulo(i,2) == 0) then + if (.not. esmfalarm1800_ring) then + allCorrect = .false. + end if + else + if (esmfalarm1800_ring) then + allCorrect = .false. + end if + end if + enddo + + call ESMF_ClockSet(clock, direction=ESMF_DIRECTION_REVERSE, rc=status) + call verify_(status) + i = 0 + do + i = i + 1 + call ESMF_ClockAdvance(clock,rc=status) + call verify_(status) + + esmfalarm900_ring = ESMF_AlarmIsRinging(esmfalarm900, rc=status) + call verify_(status) + if (.not. esmfalarm900_ring) then + allCorrect = .false. + end if + + esmfalarm1800_ring = ESMF_AlarmIsRinging(esmfalarm1800, rc=status) + call verify_(status) + if (modulo(i,2) == 0) then + if (.not. esmfalarm1800_ring) then + allCorrect = .false. + end if + else + if (esmfalarm1800_ring) then + allCorrect = .false. + end if + end if + + call ESMF_ClockGet(clock,currTime=time) + if (time == start_time) exit + enddo + + call ESMF_ClockSet(clock, direction=ESMF_DIRECTION_FORWARD, rc=status) + call verify_(status) + do i=1,nstep*2 + call ESMF_ClockAdvance(clock) + + esmfalarm900_ring = ESMF_AlarmIsRinging(esmfalarm900, rc=status) + call verify_(status) + if (.not. esmfalarm900_ring) then + allCorrect = .false. + end if + + esmfalarm1800_ring = ESMF_AlarmIsRinging(esmfalarm1800, rc=status) + call verify_(status) + if (modulo(i,2) == 0) then + if (.not. esmfalarm1800_ring) then + allCorrect = .false. + end if + else + if (esmfalarm1800_ring) then + allCorrect = .false. + end if + end if + enddo + + if (allCorrect) then + testPass = .true. + else + testPass = .false. + end if end subroutine Test_AlarmAdvRewind subroutine Test_RevAlarmSticky(dt, testPass, rc) From 4c8a9041826678e4c58260132e5f2cac36334fb1 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Thu, 2 Jan 2025 17:08:26 -0700 Subject: [PATCH 25/32] Remove Test_RevAlarmSticky This seemed like an incomplete test that wasn't testing anything new (at least at this point, with the test being incomplete). Note that a reverse sticky alarm is currently covered with Test_AlarmHang, particularly after the extra testing I added in that test. --- .../TimeMgr/tests/ESMF_AlarmUTest.F90 | 77 +------------------ 1 file changed, 3 insertions(+), 74 deletions(-) diff --git a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 index 89fe7ce465..89dde0e636 100644 --- a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 +++ b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 @@ -1241,18 +1241,6 @@ program ESMF_AlarmTest ! ---------------------------------------------------------------------------- - !EX_UTest - write(failMsg, *) " Alarms reverse with sticky set... " - write(name, *) "Test running an alarm reverse with sticky bit set " - rc = ESMF_SUCCESS - testPass = .true. - call Test_RevAlarmSticky(60._ESMF_KIND_R8, testPass, rc) - if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. - if (.not. testPass) print *, 'bad return codes discovered' - call ESMF_Test (testPass, name, failMsg, result, ESMF_SRCLINE) - - ! ---------------------------------------------------------------------------- - !EX_UTest write(failMsg, *) " Alarms with getPrevRingTime... " write(name, *) "Test getPrevRingTime... after alarm attached to clock " @@ -1471,6 +1459,9 @@ subroutine test_ReverseAlarms(testPass, rc) end subroutine Test_ReverseAlarms subroutine Test_AlarmHang(testPass, rc) + ! Note that, in addition to testing a case that led to a hang at one point, this + ! also tests the behavior of a sticky alarm with a clock running both forward and + ! reverse. logical, intent(out) :: testPass integer, intent(out) :: rc @@ -1764,68 +1755,6 @@ subroutine Test_AlarmAdvRewind(testPass, rc) end if end subroutine Test_AlarmAdvRewind -subroutine Test_RevAlarmSticky(dt, testPass, rc) -#define CONTEXT line=__LINE__,file=__FILE__ -#define CHECKRC if(ESMF_LogFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,CONTEXT,rcToReturn=rc))then;write(0,*)'app abort: ',__FILE__,__LINE__;return;endif - logical, intent(out) :: testPass - integer, parameter :: r8 = SELECTED_REAL_KIND(12) ! real r8 - real(kind=r8), intent(in) :: dt - integer :: rc - - type(ESMF_Clock) :: clock - type(ESMF_Alarm) :: alarm - type(ESMF_TimeInterval) :: esmf_ival - type(ESMF_Time) :: time, initial, finish, ring_time - real(kind=r8) :: secs - logical :: reverse_clock, sticky_alarm - - rc = ESMF_SUCCESS - - call ESMF_TimeSet(time, yy=2021, mm=4, dd=6, rc=rc) ; CHECKRC - - secs = 0 - call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) ; CHECKRC - initial = time + esmf_ival - - secs = dt*100 - call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) ; CHECKRC - finish = time + esmf_ival - - secs = dt - call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) ; CHECKRC - - clock = ESMF_Clockcreate(timeStep=esmf_ival & - ,startTime=initial,stopTime=finish & - ,refTime=time, rc=rc ) ; CHECKRC - - call ESMF_ClockSet(clock,direction=ESMF_DIRECTION_REVERSE, rc=rc) ; CHECKRC - - reverse_clock = ESMF_ClockIsReverse(clock, rc=rc) ; CHECKRC - sticky_alarm = .not.reverse_clock - - write(0,'("reverse =",x,l)') reverse_clock - write(0,'("sticky =",x,l)') sticky_alarm - - secs = dt*50 - call ESMF_TimeIntervalSet(esmf_ival,s_r8=secs,rc=rc) ; CHECKRC - ring_time = initial + esmf_ival - -#if 1 - alarm = ESMF_AlarmCreate(clock, ringTime=ring_time, sticky=sticky_alarm, & - rc=rc) ; CHECKRC -#else - alarm = ESMF_AlarmCreate(clock, ringTime=ring_time, sticky=.false., & - rc=rc) ; CHECKRC -#endif - - call ESMF_alarmPrint(alarm,options='sticky') - - testPass = .true. ! Because the C++ runtime failure cannot be caught reliably, set this to false. - -#undef CONTEXT -#undef CHECKRC -end subroutine Test_RevAlarmSticky - subroutine verify_(rc) integer, intent(in) :: rc From 0b6f73e0087c4470b3b33c8b3f81eeb06f015cdf Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Fri, 3 Jan 2025 07:36:16 -0700 Subject: [PATCH 26/32] Minor cleanup of Test_GetPrevRingTime More rework is still needed for this test so that it actually tests what it says it's testing. --- .../TimeMgr/tests/ESMF_AlarmUTest.F90 | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 index 89dde0e636..eb781b7cd5 100644 --- a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 +++ b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 @@ -1244,8 +1244,6 @@ program ESMF_AlarmTest !EX_UTest write(failMsg, *) " Alarms with getPrevRingTime... " write(name, *) "Test getPrevRingTime... after alarm attached to clock " - rc = ESMF_SUCCESS - testPass = .true. call Test_GetPrevRingTime(testPass, rc) if (testPass .and. rc /= ESMF_SUCCESS) testPass = .false. if (.not. testPass) print *, 'bad return codes discovered' @@ -1837,8 +1835,8 @@ subroutine Test_GetPrevRingTime(testPass, rc) #define CONTEXT line=__LINE__,file=__FILE__ #define CHECKRC if(ESMF_LogFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,CONTEXT,rcToReturn=rc))then;write(0,*)'app abort: ',__FILE__,__LINE__;return;endif logical, intent(out) :: testPass + integer, intent(out) :: rc integer, parameter :: r8 = SELECTED_REAL_KIND(12) ! real r8 - integer :: rc type(ESMF_Clock) :: clock type(ESMF_Alarm) :: alarm @@ -1847,9 +1845,11 @@ subroutine Test_GetPrevRingTime(testPass, rc) real(kind=r8) :: secs logical :: reverse_clock, sticky_alarm, esmf_ring integer :: i, nstep = 6, nrings + logical :: allCorrect rc = ESMF_SUCCESS - testPass = .true. + testPass = .false. + allCorrect = .true. call ESMF_TimeSet(time, yy=2021, mm=4, dd=6, rc=rc) ; CHECKRC @@ -1892,7 +1892,7 @@ subroutine Test_GetPrevRingTime(testPass, rc) call ESMF_TimePrint(ringTime,options='string') diffTime = ringTime - prevTime - if(diffTime /= esmf_ival) testPass = .false. ! both should be 20 minutes or 120 seconds + if(diffTime /= esmf_ival) allCorrect = .false. ! both should be 20 minutes or 120 seconds prevTime = ringTime end if enddo @@ -1920,6 +1920,11 @@ subroutine Test_GetPrevRingTime(testPass, rc) ! ! call ESMF_alarmPrint(alarm,options='sticky') + if (allCorrect) then + testPass = .true. + else + testPass = .false. + end if #undef CONTEXT #undef CHECKRC From e40712faed10a2de6f76d37aac4c594179c255aa Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Fri, 3 Jan 2025 09:07:43 -0700 Subject: [PATCH 27/32] Fix indentation --- src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 index eb781b7cd5..cf34063643 100644 --- a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 +++ b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 @@ -1609,7 +1609,7 @@ subroutine Test_AlarmHang(testPass, rc) if (allCorrect) then testPass = .true. else - testPass = .false. + testPass = .false. end if end subroutine Test_AlarmHang From c127912ba83493e550b493eee0ede71e082e1b1d Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Tue, 7 Jan 2025 11:37:59 -0700 Subject: [PATCH 28/32] Remove duplicate line of code --- src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C b/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C index 69a6dacf85..f6de9fab41 100644 --- a/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C +++ b/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C @@ -899,7 +899,6 @@ void Alarm::enableSticky(void){ if (rc != ESMC_NULL_POINTER) *rc = ESMF_SUCCESS; // get clock's prev time - if (rc != ESMC_NULL_POINTER) *rc = ESMF_SUCCESS; // Time clockTime = clock->currTime - clock->timeStep; // return canRingAtTime(clockTime); return ringingOnPrevTimeStep; From b8d72a9b42dad3601e0977814e39ffdbf3b4db9f Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Tue, 7 Jan 2025 12:29:14 -0700 Subject: [PATCH 29/32] Remove unused checkTurnOn function It looks like this has been effectively replaced by canRingAtTime --- .../TimeMgr/include/ESMCI_Alarm.h | 3 - src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C | 66 ------------------- 2 files changed, 69 deletions(-) diff --git a/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h b/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h index 7a000b5dcd..8cf7f60d33 100644 --- a/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h +++ b/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h @@ -257,9 +257,6 @@ class Alarm { // // < declare private interface methods here > - // check if time to turn on alarm - bool checkTurnOn(bool timeStepPositive); - // reconstruct ringBegin during ESMF_DIRECTION_REVERSE int resetRingBegin(bool timeStepPositive); diff --git a/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C b/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C index f6de9fab41..82af647e9d 100644 --- a/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C +++ b/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C @@ -1673,72 +1673,6 @@ void Alarm::clockChangeDirection(const ESMC_Direction & old_direction, // Private methods //------------------------------------------------------------------------- -//------------------------------------------------------------------------- -//BOPI -// !IROUTINE: Alarm::checkTurnOn - check if time to turn on alarm -// -// !INTERFACE: - bool Alarm::checkTurnOn( -// -// !RETURN VALUE: -// bool whether to turn on alarm -// -// !ARGUMENTS: - bool timeStepPositive) { // in - sign of clock's timeStep, -// // true: positive, false: negative -// -// !DESCRIPTION: -// Checks whether alarm should be ringing -// -//EOPI -// !REQUIREMENTS: - - #undef ESMC_METHOD - #define ESMC_METHOD "ESMCI::Alarm::checkTurnOn()" - - // The original comment few lines below indicates that the ringing state - // would be turned off elsewhere. However, it is initialized (turn off) - // here for the sake of X1 compiler. That may be taken off later. - ringingOnCurrTimeStep = false; - - bool checkRinging; - - if (clock->advanceCount != 0) { // clock has been advanced; use prevTime - checkRinging = (timeStepPositive) ? - clock->currTime >= ringTime && clock->prevTime < ringTime : - clock->currTime <= ringTime && clock->prevTime > ringTime; - } else { // clock in initial state; don't use prevTime since - // it equals currTime - checkRinging = (timeStepPositive) ? - clock->currTime >= ringTime : - clock->currTime <= ringTime ; - } - - if (checkRinging) { - // if so, refresh ringing state; if not, leave previous state alone: - // turn off determined elsewhere. - ringingOnCurrTimeStep = ringing = true; - - // note time, - ringBegin = clock->currTime; - - // and update next ringing time - bool updateNextRingingTime = true; - if (stopTime.Time::validate("initialized") == ESMF_SUCCESS) { - updateNextRingingTime = (timeStepPositive) ? - clock->currTime < (stopTime - ringInterval): - clock->currTime > (stopTime - ringInterval); - } - if (updateNextRingingTime) { - prevRingTime = ringTime; - ringTime += ringInterval; - } - } - - return(checkRinging); - -} // end Alarm::checkTurnOn - //------------------------------------------------------------------------- //BOPI // !IROUTINE: Alarm::resetRingBegin - reset ringBegin during ESMF_DIRECTION_REVERSE From a55cffaca4400a82e6d934ed7684d194db91c2f2 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Tue, 7 Jan 2025 12:37:55 -0700 Subject: [PATCH 30/32] Remove no-longer-referenced ringingOnCurrTimeStep --- src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h | 6 ------ src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h b/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h index 8cf7f60d33..251fcffe00 100644 --- a/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h +++ b/src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h @@ -127,12 +127,6 @@ class Alarm { // number of time steps. bool ringing; // (TMG 4.4) currently ringing - bool ringingOnCurrTimeStep; // was ringing immediately after - // current clock timestep. - // (could have been turned off - // later due to RingerOff or - // Disable commands or - // non-sticky alarm expiration). bool ringingOnPrevTimeStep; // was ringing immediately after // previous clock timestep. bool userChangedRingTime; // true if changed via Set(), diff --git a/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C b/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C index 82af647e9d..702b483e3e 100644 --- a/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C +++ b/src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C @@ -1595,7 +1595,7 @@ void Alarm::clockChangeDirection(const ESMC_Direction & old_direction, clock = ESMC_NULL_POINTER; ringTimeStepCount = 1; timeStepRingingCount = 0; - ringing = ringingOnCurrTimeStep = ringingOnPrevTimeStep = false; + ringing = ringingOnPrevTimeStep = false; userChangedRingTime = false; userChangedRingInterval = false; enabled = true; From cdb1c87562e1b516e940aa85b679dc4576e92f85 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Thu, 16 Jan 2025 15:48:19 -0700 Subject: [PATCH 31/32] Extend tests with alarm interval not a multiple of time step Go for an extra couple of time steps to make sure the alarm isn't ringing at those additional time steps. (But don't bother with this for the test that runs both forward & reverse, because that would be messier.) --- src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 index cf34063643..9d2c3f0dfe 100644 --- a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 +++ b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 @@ -2167,7 +2167,7 @@ subroutine ForwardAlarm_Test4(rc) allCorrect = .false. end if - do n = 1, 6 + do n = 1, 8 call ESMF_ClockAdvance(clock,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) @@ -2574,7 +2574,7 @@ subroutine ReverseAlarm_Test4(rc) if (.not. ringing) then allCorrect = .false. end if - do n = 1, 6 + do n = 1, 8 call ESMF_ClockAdvance(clock,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) From fd3a249cdaa603916014b76b45732932626f8925 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Fri, 17 Jan 2025 17:02:10 -0700 Subject: [PATCH 32/32] Add a sticky alarm to ForwardAlarm_Test4 Demonstrate that, currently, a sticky alarm operates the same way as a non-sticky alarm - though I feel this is unintuitive behavior. --- .../TimeMgr/tests/ESMF_AlarmUTest.F90 | 38 ++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 index 9d2c3f0dfe..5c2e30c801 100644 --- a/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 +++ b/src/Infrastructure/TimeMgr/tests/ESMF_AlarmUTest.F90 @@ -2131,12 +2131,12 @@ subroutine ForwardAlarm_Test4(rc) integer, intent(out) :: rc type (ESMF_Clock) :: clock - type (ESMF_Alarm) :: alarm + type (ESMF_Alarm) :: alarm, alarm_sticky type (ESMF_Time) :: startTime, stopTime, ringTime type (ESMF_TimeInterval) :: timeStep, ringTimeInterval integer :: status, n - logical :: ringing, enabled, sticky + logical :: ringing, enabled logical :: allCorrect rc = ESMF_FAILURE @@ -2160,17 +2160,29 @@ subroutine ForwardAlarm_Test4(rc) if(status /= ESMF_SUCCESS) call ESMF_Finalize() ! call ESMF_AlarmDebug(alarm,'test4',rc=status) ! if(status /= ESMF_SUCCESS) call ESMF_Finalize() + alarm_sticky = ESMF_AlarmCreate(clock, ringTime=ringTime, ringInterval=ringTimeInterval, enabled=.true., sticky=.true., name='alarm_sticky', rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + ! call ESMF_AlarmDebug(alarm_sticky,'test4',rc=status) + ! if(status /= ESMF_SUCCESS) call ESMF_Finalize() - call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + if (.not. ringing) then + allCorrect = .false. + end if + call ESMF_AlarmGet(alarm_sticky, ringing=ringing, enabled=enabled, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() if (.not. ringing) then allCorrect = .false. end if + call ESMF_AlarmRingerOff(alarm_sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + do n = 1, 8 call ESMF_ClockAdvance(clock,rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() - call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, sticky=sticky, rc=status) + call ESMF_AlarmGet(alarm, ringing=ringing, enabled=enabled, rc=status) if(status /= ESMF_SUCCESS) call ESMF_Finalize() if (n == 6) then ! Alarm should be ringing on the 6th time step, when alarm dt aligns with clock dt @@ -2183,7 +2195,23 @@ subroutine ForwardAlarm_Test4(rc) allCorrect = .false. end if end if - enddo + + call ESMF_AlarmGet(alarm_sticky, ringing=ringing, enabled=enabled, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + if (n == 6) then + ! Alarm should be ringing on the 6th time step, when alarm dt aligns with clock dt + if (.not. ringing) then + allCorrect = .false. + end if + else + ! Alarm should NOT be ringing on other time steps + if (ringing) then + allCorrect = .false. + end if + end if + call ESMF_AlarmRingerOff(alarm_sticky, rc=status) + if(status /= ESMF_SUCCESS) call ESMF_Finalize() + enddo if (allCorrect) then rc = ESMF_SUCCESS