diff --git a/src/framework/mpas_stream_manager.F b/src/framework/mpas_stream_manager.F index 06627820ec..a74c0d643e 100644 --- a/src/framework/mpas_stream_manager.F +++ b/src/framework/mpas_stream_manager.F @@ -6016,9 +6016,11 @@ subroutine stream_mgr_add_alarm_c(manager_c, streamID_c, direction_c, alarmTime_ use mpas_derived_types, only : MPAS_streamManager_type, MPAS_Clock_type, MPAS_Time_type, MPAS_TimeInterval_type, & MPAS_STREAM_MGR_NOERR, MPAS_STREAM_INPUT, MPAS_STREAM_OUTPUT, MPAS_START_TIME, & MPAS_STOP_TIME, MPAS_STREAM_PROPERTY_REF_TIME - use mpas_stream_manager, only : MPAS_stream_mgr_get_clock, MPAS_stream_mgr_add_alarm, MPAS_stream_mgr_set_property + use mpas_stream_manager, only : MPAS_stream_mgr_get_clock, MPAS_stream_mgr_add_alarm, MPAS_stream_mgr_set_property, & + MPAS_stream_mgr_get_property use mpas_kind_types, only : StrKIND - use mpas_timekeeping, only : mpas_add_clock_alarm, mpas_set_time, mpas_get_time, mpas_set_timeInterval, mpas_get_clock_time + use mpas_timekeeping, only : mpas_add_clock_alarm, mpas_set_time, mpas_get_time, mpas_set_timeInterval, mpas_get_clock_time, & + mpas_adjust_alarm_to_reference_time implicit none @@ -6034,11 +6036,14 @@ subroutine stream_mgr_add_alarm_c(manager_c, streamID_c, direction_c, alarmTime_ character(len=StrKIND) :: streamID, direction, alarmID, alarmTime, alarmInterval, alarmString type (MPAS_Time_type) :: alarmTime_local type (MPAS_TimeInterval_type) :: alarmInterval_local + character(len=StrKIND) :: streamReferenceTimeString + type (MPAS_Time_type) :: streamReferenceTime integer :: idirection - integer :: ierr + integer :: ierr, ierr_tmp ierr = 0 + ierr_tmp = 0 call c_f_pointer(manager_c, manager) call mpas_c_to_f_string(streamID_c, streamID) @@ -6061,23 +6066,36 @@ subroutine stream_mgr_add_alarm_c(manager_c, streamID_c, direction_c, alarmTime_ call MPAS_stream_mgr_get_clock(manager, clock) if (trim(alarmTime) == 'start' .and. trim(alarmInterval) == 'final_only') then - alarmTime_local = mpas_get_clock_time(clock, MPAS_STOP_TIME, ierr=ierr) + alarmTime_local = mpas_get_clock_time(clock, MPAS_STOP_TIME, ierr=ierr_tmp) + ierr = ior(ierr, ierr_tmp) call mpas_get_time(alarmTime_local, dateTimeString=alarmString) - call MPAS_stream_mgr_set_property(manager, streamID, MPAS_STREAM_PROPERTY_REF_TIME, alarmString, ierr=ierr) + call MPAS_stream_mgr_set_property(manager, streamID, MPAS_STREAM_PROPERTY_REF_TIME, alarmString, ierr=ierr_tmp) + ierr = ior(ierr, ierr_tmp) else if (trim(alarmTime) == 'start') then - alarmTime_local = mpas_get_clock_time(clock, MPAS_START_TIME, ierr=ierr) + alarmTime_local = mpas_get_clock_time(clock, MPAS_START_TIME, ierr=ierr_tmp) + ierr = ior(ierr, ierr_tmp) else call mpas_set_time(alarmTime_local, dateTimeString=alarmTime) end if if (trim(alarmInterval) == 'initial_only' .or. trim(alarmInterval) == 'final_only') then - call mpas_add_clock_alarm(clock, alarmID, alarmTime_local, ierr=ierr) + call mpas_add_clock_alarm(clock, alarmID, alarmTime_local, ierr=ierr_tmp) + ierr = ior(ierr, ierr_tmp) else call mpas_set_timeInterval(alarmInterval_local, timeString=alarmInterval) - call mpas_add_clock_alarm(clock, alarmID, alarmTime_local, alarmTimeInterval=alarmInterval_local, ierr=ierr) + call mpas_add_clock_alarm(clock, alarmID, alarmTime_local, alarmTimeInterval=alarmInterval_local, ierr=ierr_tmp) + ierr = ior(ierr, ierr_tmp) + ! Now calibrate alarm to use the stream's reference time as the time coordinate origin for the stream's output alarm. + call MPAS_stream_mgr_get_property(manager, streamID, MPAS_STREAM_PROPERTY_REF_TIME, streamReferenceTimeString, ierr=ierr_tmp) + ierr = ior(ierr, ierr_tmp) + call mpas_set_time(streamReferenceTime, dateTimeString=streamReferenceTimeString, ierr=ierr_tmp) + ierr = ior(ierr, ierr_tmp) + call mpas_adjust_alarm_to_reference_time(clock, alarmID, streamReferenceTime, ierr) + ierr = ior(ierr, ierr_tmp) end if - call MPAS_stream_mgr_add_alarm(manager, streamID, alarmID, idirection, ierr=ierr) + call MPAS_stream_mgr_add_alarm(manager, streamID, alarmID, idirection, ierr=ierr_tmp) + ierr = ior(ierr, ierr_tmp) if (ierr == MPAS_STREAM_MGR_NOERR) then ierr_c = 0 diff --git a/src/framework/mpas_timekeeping.F b/src/framework/mpas_timekeeping.F index a799faf97c..c6de8f0aed 100644 --- a/src/framework/mpas_timekeeping.F +++ b/src/framework/mpas_timekeeping.F @@ -969,6 +969,75 @@ subroutine mpas_reset_clock_alarm(clock, alarmID, interval, ierr) end subroutine mpas_reset_clock_alarm + ! Adjust the previous ring time of a recurring alarm to be away from a provided reference time + ! by an integer multiple of the alarm's interval. + ! This is useful if the alarm's default prevRingTime, which is the current time when the alarm + ! is created, is not desired. + subroutine mpas_adjust_alarm_to_reference_time(clock, alarmID, referenceTime, ierr) + + implicit none + + type (MPAS_Clock_type), intent(inout) :: clock + character (len=*), intent(in) :: alarmID + type (MPAS_Time_type) :: referenceTime + type (MPAS_Time_type) :: now + integer, intent(out) :: ierr + + ! Local variables + type (MPAS_Alarm_type), pointer :: alarmPtr + type (MPAS_TimeInterval_type) :: searchInterval, searchRemainder + integer (kind=I8KIND) :: nDivs + integer :: threadNum + integer :: ierr_tmp + + ierr = 0 + ierr_tmp = 0 + + threadNum = mpas_threading_get_thread_num() + + if ( threadNum == 0 ) then + alarmPtr => clock % alarmListHead + do while (associated(alarmPtr)) + + if (trim(alarmPtr % alarmID) == trim(alarmID)) then + + if (alarmPtr % isRecurring) then + !call mpas_print_alarm(clock, alarmID, ierr_tmp) + now = mpas_get_clock_time(clock, MPAS_NOW, ierr_tmp) + ierr = ior(ierr, ierr_tmp) + if(clock % direction == MPAS_FORWARD) then + 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) + endif + else ! MPAS_REVERSE + 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) + endif + end if ! forward direction + !call mpas_print_alarm(clock, alarmID, ierr_tmp) + end if ! isRecurring + exit ! exit after we found the alarm we were looking for + end if ! if this alarm we were looking for + alarmPtr => alarmPtr % next + end do + end if ! thread check + + !$omp barrier + end subroutine mpas_adjust_alarm_to_reference_time + + ! specify a valid previousRingTime for each alarm subroutine mpas_calibrate_alarms(clock, ierr)