Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Provide consistency in setting of prevRingTime for alarms when changi…
…ng ref time

This commit aims to provide consistency in the ringing behavior of recurring
alarms after their reference time has been adjusted with a call to
mpas_adjust_alarm_to_reference_time. Now, adjusting the reference time for an
alarm will always leave that alarm in a state such that it is considered by the
mpas_is_alarm_ringing routine to be ringing at the current time.

For simplicity of discussion, consider only a clock that is running forward in
time. The objective of the mpas_adjust_alarm_to_reference_time routine is to set
the prevRingTime (previous ring time) of a recurring alarm to (1) a time that
differs from the specified reference time by an integer multiple of the alarm
interval; and (2) the latest such time that is not after the current time on the
clock.

Prior to this commit, the logic in the mpas_adjust_alarm_to_reference_time
routine resulted in one of two outcomes:

(1) If the difference between the reference time and the current time is
divisible by the alarm interval, the prevRingTime becomes the current time, as
illustrated below.

    ring            ring            ring            ring
     v               v               v               v
  -----------------------------------------------------------
                                     ^
                                    now
                                prevRingTime

(2) Otherwise, the prevRingTime becomes the latest time before the current time
that lies on an integer multiple of the alarm interval away from the reference
time, as illustrated below.

    ring            ring            ring            ring
     v               v               v               v
  -----------------------------------------------------------
                     ^           ^
                prevRingTime    now

To determine whether a recurring alarm is ringing, the alarm's interval is added
to the alarm's prevRingTime. If the result is on or before the current time, the
alarm is ringing; otherwise, if the result is later than the current time, the
alarm is not ringing. As a consequence, outcome (1) from the
mpas_adjust_alarm_to_reference_time leads to an alarm that is ringing after the
call to the routine, while outcome(2) leads to an alarm that is not yet ringing.

In order to rectify the inconsistency in whether an alarm is ringing depending
on where its reference time is set relative to the current time, the
prevRingTime for an alarm is always set to be at least one full alarm interval
before the current time. Whether the difference between the current time and the
reference time is evenly divisible by the alarm's ring interval or not, a query
of the alarm's status immediately following the call to
mpas_adjust_alarm_to_reference_time will always show that it is ringing.

This commit makes changes to the logic for both a forward and a backward running
clock in the mpas_adjust_alarm_to_reference_time routine, although it appears
that no code actually makes use of a backward running clock at present.

Note: At present, the logic is not quite as elegant as one might expect it
should be. In future, if the interval_division routine handled negative
intervals like the analog of

  (-2.75 % 1.0) => 0.25

then there may be no need for if-tests within blocks for each clock direction.
  • Loading branch information
mgduda committed May 20, 2025
commit 66d310a0d1934268f6ba30a28703a3474a738ba2
22 changes: 15 additions & 7 deletions src/framework/mpas_timekeeping.F
Original file line number Diff line number Diff line change
Expand Up @@ -1000,13 +1000,17 @@ subroutine mpas_adjust_alarm_to_reference_time(clock, alarmID, referenceTime, ie
! Local variables
type (MPAS_Alarm_type), pointer :: alarmPtr
type (MPAS_TimeInterval_type) :: searchInterval, searchRemainder
type (MPAS_TimeInterval_type) :: zeroInterval
integer (kind=I8KIND) :: nDivs
integer :: threadNum
integer :: ierr_tmp


ierr = 0
ierr_tmp = 0

call mpas_set_timeInterval(zeroInterval, S=0)

threadNum = mpas_threading_get_thread_num()

if ( threadNum == 0 ) then
Expand All @@ -1023,22 +1027,26 @@ subroutine mpas_adjust_alarm_to_reference_time(clock, alarmID, referenceTime, ie
if (now > referenceTime) then
searchInterval = now - referenceTime
call mpas_interval_division(referenceTime, searchInterval, alarmPtr % ringTimeInterval, nDivs, searchRemainder)
alarmPtr % prevRingTime = now - searchRemainder
else
searchInterval = referenceTime - now
call mpas_interval_division(referenceTime, searchInterval, alarmPtr % ringTimeInterval, nDivs, searchRemainder)
alarmPtr % prevRingTime = now - (alarmPtr % ringTimeInterval - searchRemainder)
if (searchRemainder /= zeroInterval) then
searchRemainder = alarmPtr % ringTimeInterval - searchRemainder
end if
endif
else ! MPAS_REVERSE
alarmPtr % prevRingTime = now - alarmPtr % ringTimeInterval - searchRemainder
else ! MPAS_BACKWARD
if (now < referenceTime) then
searchInterval = now - referenceTime
searchInterval = referenceTime - now
call mpas_interval_division(referenceTime, searchInterval, alarmPtr % ringTimeInterval, nDivs, searchRemainder)
alarmPtr % prevRingTime = now - searchRemainder
else
searchInterval = referenceTime - now
searchInterval = now - referenceTime
call mpas_interval_division(referenceTime, searchInterval, alarmPtr % ringTimeInterval, nDivs, searchRemainder)
alarmPtr % prevRingTime = now - (alarmPtr % ringTimeInterval - searchRemainder)
if (searchRemainder /= zeroInterval) then
searchRemainder = alarmPtr % ringTimeInterval - searchRemainder
end if
endif
alarmPtr % prevRingTime = now + alarmPtr % ringTimeInterval + searchRemainder
end if ! forward direction
!call mpas_print_alarm(clock, alarmID, ierr_tmp)
end if ! isRecurring
Expand Down