Skip to content

Commit 681024d

Browse files
committed
Enable ESMF_AlarmWillRingNext() for repeat clock.
1 parent a4da9b3 commit 681024d

File tree

3 files changed

+350
-90
lines changed

3 files changed

+350
-90
lines changed

src/Infrastructure/TimeMgr/include/ESMCI_Alarm.h

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -264,16 +264,18 @@ class Alarm {
264264
//
265265
private:
266266
//
267-
// < declare private interface methods here >
268-
269-
// check if time to turn on alarm
270-
bool checkTurnOn(bool timeStepPositive);
271-
272-
// reconstruct ringBegin during ESMF_DIRECTION_REVERSE
273-
int resetRingBegin(bool timeStepPositive);
274-
275-
// friend class alarm
276-
friend class Clock;
267+
// < declare private interface methods here >
268+
269+
int checkRingingDueToRepeatClockTimeStep(Time &prevTime, Time &currTime, TimeInterval &timeStep, bool &ringForTimeStep) const;
270+
271+
// check if time to turn on alarm
272+
bool checkTurnOn(bool timeStepPositive);
273+
274+
// reconstruct ringBegin during ESMF_DIRECTION_REVERSE
275+
int resetRingBegin(bool timeStepPositive);
276+
277+
// friend class alarm
278+
friend class Clock;
277279

278280
//
279281
//EOP

src/Infrastructure/TimeMgr/src/ESMCI_Alarm.C

Lines changed: 154 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,14 @@ int Alarm::count=0;
870870

871871
} // end Alarm::ringerOff
872872

873+
874+
875+
876+
877+
878+
879+
880+
873881
//-------------------------------------------------------------------------
874882
//BOP
875883
// !IROUTINE: Alarm::isRinging - check if Alarm is ringing
@@ -910,6 +918,123 @@ int Alarm::count=0;
910918

911919
} // end Alarm::isRinging
912920

921+
922+
//-------------------------------------------------------------------------
923+
//BOPI
924+
// !IROUTINE: Alarm::checkRingingDueToRepeatClockTimeStep - an internal routine
925+
// that checks if a repeat clock alarm should ring when it does a particular
926+
// time step
927+
//
928+
// !INTERFACE:
929+
int Alarm::checkRingingDueToRepeatClockTimeStep(Time &prevTime, Time &currTime, TimeInterval &timeStep, bool &ringingDueToTimeStep) const {
930+
//
931+
// !RETURN VALUE:
932+
// return code
933+
//
934+
// !ARGUMENTS:
935+
// prevTime - The time before it took the time step
936+
// currTime - The time now that it look the time step
937+
// timeStep - The time step that it took to get from prev to curr
938+
// ringingDuetoTimeStep - should the alarm rign for the specified time step
939+
//
940+
// !DESCRIPTION:
941+
// an internal routine that checks if a repeat clock alarm should ring when it does a particular
942+
// time step. Note that this doesn't change any state in the alarm, it just checks for ringing.
943+
//
944+
//EOPI
945+
// !REQUIREMENTS: developer's guide for classes
946+
947+
#undef ESMC_METHOD
948+
#define ESMC_METHOD "ESMCI::Alarm::checkRingingDueToRepeatClockTimeStep()"
949+
950+
// Initialize return code; assume routine not implemented
951+
int rc = ESMC_RC_NOT_IMPL;
952+
953+
// Useful
954+
TimeInterval zeroTimeInterval(0,0,1,0,0,0);
955+
Time repeatTime=clock->startTime+clock->repeatDuration;
956+
957+
// Init
958+
ringingDueToTimeStep=false;
959+
960+
// If the timeStep is bigger than the repeatDuration, then alarms are
961+
// ringing no matter what
962+
if (timeStep >= clock->repeatDuration) {
963+
ringingDueToTimeStep=true;
964+
}
965+
966+
// If not ringing yet, check for alarms due to ringTime and implied ringTimes
967+
if (!ringingDueToTimeStep) {
968+
969+
// If no ringInterval, then just check the single ringTime
970+
if (ringInterval == zeroTimeInterval) {
971+
// If currTime is after prevtime, then it needs to be within prevTime to currTime
972+
if (currTime > prevTime) {
973+
if ((ringTime > prevTime) && (ringTime <= currTime)) {
974+
ringingDueToTimeStep=true;
975+
}
976+
} else if (currTime < prevTime) { // It needs to be within the wrapped time
977+
if ((ringTime > prevTime) && (ringTime < repeatTime)) {
978+
ringingDueToTimeStep=true;
979+
} else if ((ringTime >= clock->startTime) && (ringTime <= currTime)) {
980+
ringingDueToTimeStep=true;
981+
}
982+
} else { // prevTime == currTime, it has to be right on the currTime
983+
if (ringTime == currTime) {
984+
ringingDueToTimeStep=true;
985+
}
986+
}
987+
} else { // Check for ringing due to ringInterval
988+
989+
// Loop checking the set of times implied by the ringInterval
990+
bool wrapped=false;
991+
Time tmpRingTime=ringTime;
992+
while (true) {
993+
994+
// Check for tmpRingTime ringing
995+
if (currTime > prevTime) { // If currTime is after prevtime, then it needs to be within prevTime to currTime
996+
if ((tmpRingTime > prevTime) && (tmpRingTime <= currTime)) {
997+
ringingDueToTimeStep=true;
998+
}
999+
} else if (currTime < prevTime) { // It needs to be within the wrapped time
1000+
if ((tmpRingTime > prevTime) && (tmpRingTime < repeatTime)) {
1001+
ringingDueToTimeStep=true;
1002+
} else if ((tmpRingTime >= clock->startTime) && (tmpRingTime <= currTime)) {
1003+
ringingDueToTimeStep=true;
1004+
}
1005+
} else { // prevTime == currTime, it has to be right on the currTime
1006+
if (tmpRingTime == currTime) {
1007+
ringingDueToTimeStep=true;
1008+
}
1009+
}
1010+
1011+
// Check for being done
1012+
if (ringingDueToTimeStep) break;
1013+
1014+
// Advance to the next ringtime
1015+
tmpRingTime=tmpRingTime+ringInterval;
1016+
1017+
// If we're past repeatTime, then wrap
1018+
if (tmpRingTime >= repeatTime) {
1019+
tmpRingTime = clock->startTime + (tmpRingTime-repeatTime);
1020+
wrapped=true;
1021+
}
1022+
1023+
// If we've wrapped and passed the original ringTime, then stop
1024+
if (wrapped && (tmpRingTime > ringTime)) break;
1025+
1026+
}
1027+
}
1028+
}
1029+
1030+
1031+
// Output success
1032+
rc = ESMF_SUCCESS;
1033+
return(rc);
1034+
1035+
} // end Alarm::checkRingingDueToRepeatClockTimeStep
1036+
1037+
9131038
//-------------------------------------------------------------------------
9141039
//BOP
9151040
// !IROUTINE: Alarm::willRingNext - check if Alarm will ring upon the next clock timestep
@@ -963,10 +1088,30 @@ int Alarm::count=0;
9631088
Time clockNextTime;
9641089
clock->Clock::getNextTime(&clockNextTime, timeStep);
9651090

1091+
9661092
// if specified, use passed-in timestep, otherwise use clock's
9671093
TimeInterval tStep = (timeStep != ESMC_NULL_POINTER) ?
9681094
*timeStep : clock->timeStep;
9691095

1096+
1097+
// IF a repeat clock, handle that and leave
1098+
if (clock->repeat) {
1099+
int localrc;
1100+
bool willRing = false;
1101+
1102+
// Check if the alarm should go off due to the time step that will happen next
1103+
bool ringingDueToCurrTimeStep=false;
1104+
localrc=checkRingingDueToRepeatClockTimeStep(clock->currTime, clockNextTime, tStep, willRing);
1105+
if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) {
1106+
return false;
1107+
}
1108+
1109+
// Set output and exit
1110+
if (rc != ESMC_NULL_POINTER) *rc = ESMF_SUCCESS;
1111+
return(willRing);
1112+
}
1113+
1114+
9701115
// get timestep direction: positive or negative
9711116
bool positive = tStep.TimeInterval::absValue() == tStep ? true : false;
9721117

@@ -1181,9 +1326,10 @@ int Alarm::count=0;
11811326
//EOP
11821327
// !REQUIREMENTS: TMG4.4, 4.6
11831328

1184-
#undef ESMC_METHOD
1185-
#define ESMC_METHOD "ESMCI::Alarm::checkRingTime()"
1186-
1329+
#undef ESMC_METHOD
1330+
#define ESMC_METHOD "ESMCI::Alarm::checkRingTime()"
1331+
int localrc;
1332+
11871333
if (this == ESMC_NULL_POINTER) {
11881334
ESMC_LogDefault.MsgFoundError(ESMC_RC_PTR_NULL,
11891335
"; 'this' pointer is NULL.", ESMC_CONTEXT, rc);
@@ -1192,7 +1338,7 @@ int Alarm::count=0;
11921338

11931339
// default return code
11941340
if (rc != ESMC_NULL_POINTER) *rc = ESMC_RC_NOT_IMPL;
1195-
1341+
11961342
// must be associated with a clock
11971343
if(clock == ESMC_NULL_POINTER) {
11981344
char logMsg[2*ESMF_MAXSTR];
@@ -1231,84 +1377,13 @@ int Alarm::count=0;
12311377
// Time at which we repeat
12321378
Time repeatTime=clock->startTime+clock->repeatDuration;
12331379

1234-
//// See what the ringing state is due to the time step that just happened
1380+
// Check if the alarm should go off due to the time step that just happened
12351381
bool ringingDueToCurrTimeStep=false;
1236-
1237-
// If the timeStep is bigger than the repeatDuration, then alarms are
1238-
// ringing no matter what
1239-
if (clock->currAdvanceTimeStep >= clock->repeatDuration) {
1240-
ringingDueToCurrTimeStep=true;
1382+
localrc=checkRingingDueToRepeatClockTimeStep(prevTime, clock->currTime, clock->currAdvanceTimeStep, ringingDueToCurrTimeStep);
1383+
if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) {
1384+
return false;
12411385
}
12421386

1243-
1244-
// If not ringing yet, check for alarms due to ringTime and implied ringTimes
1245-
if (!ringingDueToCurrTimeStep) {
1246-
1247-
// If no ringInterval, then just check the single ringTime
1248-
if (ringInterval == zeroTimeInterval) {
1249-
// If currTime is after prevtime, then it needs to be within prevTime to currTime
1250-
if (clock->currTime > prevTime) {
1251-
if ((ringTime > prevTime) && (ringTime <= clock->currTime)) {
1252-
ringingDueToCurrTimeStep=true;
1253-
}
1254-
} else if (clock->currTime < prevTime) { // It needs to be within the wrapped time
1255-
if ((ringTime > prevTime) && (ringTime < repeatTime)) {
1256-
ringingDueToCurrTimeStep=true;
1257-
} else if ((ringTime >= clock->startTime) && (ringTime <= clock->currTime)) {
1258-
ringingDueToCurrTimeStep=true;
1259-
}
1260-
} else { // prevTime == currTime, it has to be right on the currTime
1261-
if (ringTime == clock->currTime) {
1262-
ringingDueToCurrTimeStep=true;
1263-
}
1264-
}
1265-
} else { // Check for ringing due to ringInterval
1266-
1267-
// Loop checking the set of times implied by the ringInterval
1268-
bool wrapped=false;
1269-
Time tmpRingTime=ringTime;
1270-
while (true) {
1271-
1272-
// Check for tmpRingTime ringing
1273-
if (clock->currTime > prevTime) { // If currTime is after prevtime, then it needs to be within prevTime to currTime
1274-
if ((tmpRingTime > prevTime) && (tmpRingTime <= clock->currTime)) {
1275-
ringingDueToCurrTimeStep=true;
1276-
}
1277-
} else if (clock->currTime < prevTime) { // It needs to be within the wrapped time
1278-
if ((tmpRingTime > prevTime) && (tmpRingTime < repeatTime)) {
1279-
ringingDueToCurrTimeStep=true;
1280-
} else if ((tmpRingTime >= clock->startTime) && (tmpRingTime <= clock->currTime)) {
1281-
ringingDueToCurrTimeStep=true;
1282-
}
1283-
} else { // prevTime == currTime, it has to be right on the currTime
1284-
if (tmpRingTime == clock->currTime) {
1285-
ringingDueToCurrTimeStep=true;
1286-
}
1287-
}
1288-
1289-
// Check for being done
1290-
if (ringingDueToCurrTimeStep) break;
1291-
1292-
// Advance to the next ringtime
1293-
tmpRingTime=tmpRingTime+ringInterval;
1294-
1295-
// If we're past repeatTime, then wrap
1296-
if (tmpRingTime >= repeatTime) {
1297-
tmpRingTime = clock->startTime + (tmpRingTime-repeatTime);
1298-
wrapped=true;
1299-
}
1300-
1301-
// If we've wrapped and passed the original ringTime, then stop
1302-
if (wrapped && (tmpRingTime > ringTime)) break;
1303-
1304-
}
1305-
}
1306-
}
1307-
1308-
1309-
1310-
//// Check for ringing due to repeatCount??
1311-
13121387
// Turn alarm on and off depending on whether we are on the current time step and whether we were already on
13131388
if (ringingDueToCurrTimeStep) {
13141389

0 commit comments

Comments
 (0)