<p><b>croesch@ucar.edu</b> 2011-08-10 17:39:55 -0600 (Wed, 10 Aug 2011)</p><p>BRANCH COMMIT<br>
<br>
Replace ESMF Alarms with local implementation<br>
Add timeString parsing<br>
Add addtional error checks and messages<br>
Update alarm interval logic<br>
<br>
M src/framework/module_mpas_timekeeping.F<br>
</p><hr noshade><pre><font color="gray">Modified: branches/time_manager/src/framework/module_mpas_timekeeping.F
===================================================================
--- branches/time_manager/src/framework/module_mpas_timekeeping.F        2011-08-01 18:18:21 UTC (rev 933)
+++ branches/time_manager/src/framework/module_mpas_timekeeping.F        2011-08-10 23:39:55 UTC (rev 934)
@@ -4,25 +4,25 @@
use ESMF_Stubs
use ESMF_CalendarMod
use ESMF_ClockMod
- use ESMF_AlarmMod
- use ESMF_AlarmClockMod
use ESMF_TimeMod
use ESMF_TimeIntervalMod
+ private :: MPAS_CalibrateAlarms
+ private :: MPAS_inRingingEnvelope
integer, parameter :: MPAS_MAX_ALARMS = 20
integer, parameter :: MPAS_NOW = 0, &
MPAS_START_TIME = 1, &
MPAS_STOP_TIME = 2
- integer, parameter :: MPAS_FORWARD = 0, &
- MPAS_BACKWARD = 1
+ integer, parameter :: MPAS_FORWARD = 1, &
+ MPAS_BACKWARD = -1
integer, parameter :: MPAS_GREGORIAN = 0, &
MPAS_GREGORIAN_NOLEAP = 1, &
MPAS_360DAY = 2
integer :: TheCalendar
- integer, dimension(12), parameter :: daysInMonth = (/31,28,31,30,31,30,31,31,30,31,30,31/)
+ integer, dimension(12), parameter :: daysInMonth = (/31,28,31,30,31,30,31,31,30,31,30,31/)
integer, dimension(12), parameter :: daysInMonthLeap = (/31,29,31,30,31,30,31,31,30,31,30,31/)
@@ -35,15 +35,15 @@
end type
type MPAS_Alarm_type
- type (ESMF_Alarm) :: a
- type (ESMF_Time) :: ringTime
- type (ESMF_Time) :: relativeToTime
- type (ESMF_TimeInterval) :: ringTimeInterval
- logical :: recurring
integer :: alarmID
+ logical :: isRecurring
+ logical :: isSet
+ type (MPAS_Time_type) :: ringTime
+ type (MPAS_Time_type) :: prevRingTime
+ type (MPAS_TimeInterval_type) :: ringTimeInterval
type (MPAS_Alarm_type), pointer :: next
end type
-
+
type MPAS_Clock_type
integer :: direction
integer :: nAlarms
@@ -51,7 +51,6 @@
type (MPAS_Alarm_type), pointer :: alarmListHead
end type
-
interface operator (+)
module procedure add_t_ti
module procedure add_ti_ti
@@ -197,7 +196,6 @@
alarmPtr => clock % alarmListHead
do while (associated(alarmPtr))
clock % alarmListHead => alarmPtr % next
- call ESMF_AlarmDestroy(alarmPtr % a, rc=ierr)
deallocate(alarmPtr)
alarmPtr => clock % alarmListHead
end do
@@ -265,9 +263,6 @@
subroutine MPAS_setClockDirection(clock, direction, ierr)
-!TODO: Need to somehow set PrevRingTime for any recurring alarms that are not
-! ringing so that they will be correctly triggered when advancing time in
-! a different direction
implicit none
@@ -299,85 +294,11 @@
-
- ! specify a valid previousRingTime for each alarm
- subroutine MPAS_CalibrateAlarms(clock, ierr)
-
- type (MPAS_Clock_type), intent(inout) :: clock
- integer, intent(out), optional :: ierr
-
- type (MPAS_Alarm_type), pointer :: alarmPtr
-
- type (MPAS_Time_type) :: now
- type (MPAS_Time_type) :: previousRingTime
- type (MPAS_Time_type) :: negativeNeighborRingTime
- type (MPAS_Time_type) :: positiveNeighborRingTime
-
- type (MPAS_TimeInterval_type) :: ringTimeInterval
-
- now = MPAS_getClockTime(clock, MPAS_NOW, ierr)
- alarmPtr => clock % alarmListHead
- do while (associated(alarmPtr))
-
- if (alarmPtr % recurring) then
-
- call ESMF_AlarmGetPrevRingTime(alarmPtr % a, previousRingTime % t, ierr)
- ringTimeInterval % ti = alarmPtr % ringTimeInterval
-
- if (previousRingTime <= now) then
-
- do while(previousRingTime <= now)
- previousRingTime = previousRingTime + ringTimeInterval
- end do
- positiveNeighborRingTime = previousRingTime
-
- do while(previousRingTime >= now)
- previousRingTime = previousRingTime - ringTimeInterval
- end do
- negativeNeighborRingTime = previousRingTime
-
- else
-
- do while(previousRingTime >= now)
- previousRingTime = previousRingTime - ringTimeInterval
- end do
- negativeNeighborRingTime = previousRingTime
-
- do while(previousRingTime <= now)
- previousRingTime = previousRingTime + ringTimeInterval
- end do
- positiveNeighborRingTime = previousRingTime
-
- end if
-
- if (clock % direction == MPAS_FORWARD) then
- call ESMF_AlarmSetPrevRingTime(alarmPtr % a, negativeNeighborRingTime % t, ierr)
- else
- call ESMF_AlarmSetPrevRingTime(alarmPtr % a, positiveNeighborRingTime % t, ierr)
- end if
-
- else
- call ESMF_AlarmSet(alarmPtr % a, &
- RingTime=alarmPtr%RingTime, &
- Enabled=.true., rc=ierr)
- end if
-
- alarmPtr => alarmPtr % next
-
- end do
-
- if (present(ierr)) then
- if (ierr == ESMF_SUCCESS) ierr = 0
- end if
-
- end subroutine MPAS_CalibrateAlarms
-
-
integer function MPAS_getClockDirection(clock, ierr)
implicit none
- type (MPAS_Clock_type), intent(inout) :: clock
+ type (MPAS_Clock_type), intent(in) :: clock
integer, intent(out), optional :: ierr
write(0,*) 'Called MPAS_getClockDirection'
@@ -410,7 +331,7 @@
implicit none
- type (MPAS_Clock_type), intent(inout) :: clock
+ type (MPAS_Clock_type), intent(in) :: clock
integer, intent(out), optional :: ierr
type (MPAS_TimeInterval_type) :: timeStep
@@ -486,7 +407,7 @@
implicit none
- type (MPAS_Clock_type), intent(inout) :: clock
+ type (MPAS_Clock_type), intent(in) :: clock
integer, intent(in) :: whichTime
integer, intent(out), optional :: ierr
@@ -556,23 +477,21 @@
clock % nAlarms = clock % nAlarms + 1
+ alarmPtr % isSet = .true.
+ alarmPtr % ringTime = alarmTime
+
+
if (present(alarmTimeInterval)) then
- alarmPtr % a = ESMF_AlarmCreate(clock % c, &
- RingTime=alarmTime%t, &
- RingInterval=alarmTimeInterval%ti, &
- Enabled=.true., &
- rc=ierr)
- alarmPtr % ringTime = alarmTime%t
- alarmPtr % relativeToTime = alarmTime%t
- alarmPtr % ringTimeInterval = alarmTimeInterval%ti
- alarmPtr % recurring = .true.
+ alarmPtr % isRecurring = .true.
+ alarmPtr % ringTimeInterval = alarmTimeInterval
+ if(clock % direction == MPAS_FORWARD) then
+ alarmPtr % prevRingTime = alarmTime - alarmTimeInterval
+ else
+ alarmPtr % prevRingTime = alarmTime + alarmTimeInterval
+ end if
else
- alarmPtr % a = ESMF_AlarmCreate(clock % c, &
- RingTime=alarmTime%t, &
- Enabled=.true., &
- rc=ierr)
- alarmPtr % ringTime = alarmTime%t
- alarmPtr % recurring = .false.
+ alarmPtr % isRecurring = .false.
+ alarmPtr % prevRingTime = alarmTime
end if
if (present(ierr)) then
if (ierr == ESMF_SUCCESS) ierr = 0
@@ -581,6 +500,36 @@
end subroutine MPAS_addClockAlarm
+ subroutine MPAS_removeClockAlarm(clock, alarmID, ierr)
+
+ implicit none
+
+ type (MPAS_Clock_type), intent(inout) :: clock
+ integer, intent(in) :: alarmID
+ integer, intent(out), optional :: ierr
+
+ type (MPAS_Alarm_type), pointer :: alarmPtr
+ type (MPAS_Alarm_type), pointer :: alarmParentPtr
+
+ write(0,*) 'Called MPAS_removeClockAlarm'
+ if (present(ierr)) ierr = 0
+
+ alarmPtr => clock % alarmListHead
+ alarmParentPtr = alarmPtr
+ do while (associated(alarmPtr))
+ if (alarmPtr % alarmID == alarmID) then
+ alarmParentPtr % next => alarmPtr % next
+ deallocate(alarmPtr)
+ exit
+ end if
+ alarmParentPtr = alarmPtr
+ alarmPtr => alarmPtr % next
+ end do
+
+ end subroutine MPAS_removeClockAlarm
+
+
+
subroutine MPAS_printAlarm(clock, alarmID, ierr)
implicit none
@@ -591,19 +540,30 @@
type (MPAS_Alarm_type), pointer :: alarmPtr
+ type (MPAS_TimeInterval_type) :: alarmTimeInterval
+ type (MPAS_Time_type) :: alarmTime
+ character (len=32) :: printString
+
ierr = 0
alarmPtr => clock % alarmListHead
do while (associated(alarmPtr))
if (alarmPtr % alarmID == alarmID) then
- write(0,*) 'ALARM ',alarmID
- write(0,*) alarmPtr % a % alarmint % ID
- write(0,*) alarmPtr % a % alarmint % AlarmMutex
- write(0,*) alarmPtr % a % alarmint % Ringing
- write(0,*) alarmPtr % a % alarmint % Enabled
- write(0,*) alarmPtr % a % alarmint % RingTimeSet
- write(0,*) alarmPtr % a % alarmint % RingIntervalSet
- write(0,*) alarmPtr % a % alarmint % StopTimeSet
+ write(0,*) 'ALARM ', alarmID
+
+ write(0,*) 'isRecurring', alarmPtr % isRecurring
+
+ write(0,*) 'isSet', alarmPtr % isSet
+
+ call MPAS_getTime(alarmPtr % ringTime, dateTimeString=printString, ierr=ierr)
+ write(0,*) 'ringTime', printString
+
+ call MPAS_getTime(alarmPtr % prevRingTime, dateTimeString=printString, ierr=ierr)
+ write(0,*) 'prevRingTime', printString
+
+ call MPAS_getTimeInterval(alarmPtr % ringTimeInterval, timeString=printString, ierr=ierr)
+ write(0,*) 'ringTimeInterval', printString
+
exit
end if
alarmPtr => alarmPtr % next
@@ -612,46 +572,31 @@
end subroutine MPAS_printAlarm
+
logical function MPAS_isAlarmRinging(clock, alarmID, interval, ierr)
-! TODO: check for alarms ringing within the specified interval rather than just now
implicit none
- type (MPAS_Clock_type), intent(inout) :: clock ! BETTER IF INTENT(IN)
+ type (MPAS_Clock_type), intent(in) :: clock
integer, intent(in) :: alarmID
type (MPAS_TimeInterval_type), intent(in), optional :: interval
integer, intent(out), optional :: ierr
type (MPAS_Alarm_type), pointer :: alarmPtr
- type (ESMF_TimeInterval) :: timeStep
- type (MPAS_TimeInterval_type) :: userInterval
write(0,*) 'Called MPAS_isAlarmRinging'
if (present(ierr)) ierr = 0
MPAS_isAlarmRinging = .false.
+
alarmPtr => clock % alarmListHead
do while (associated(alarmPtr))
if (alarmPtr % alarmID == alarmID) then
- if (present(interval)) then
- userInterval = interval
- call ESMF_ClockGet(clock % c, TimeStep=timeStep, rc=ierr)
- call ESMF_ClockSet(clock % c, TimeStep=userInterval % ti, rc=ierr)
- call ESMF_ClockAdvance(clock % c, rc=ierr)
- MPAS_isAlarmRinging = ESMF_AlarmIsRinging(alarmPtr % a, rc=ierr)
- userInterval = -userInterval
- call ESMF_ClockSet(clock % c, TimeStep=userInterval % ti, rc=ierr)
- call ESMF_ClockAdvance(clock % c, rc=ierr)
- call ESMF_ClockSet(clock % c, TimeStep=timeStep, rc=ierr)
-! TODO: Do these next two steps only if the alarm was not already ringing?
- call ESMF_AlarmRingerOff(alarmPtr % a, rc=ierr)
- call ESMF_AlarmSet(alarmPtr % a, RingTime=alarmPtr % RingTime, Enabled=.true., rc=ierr)
- else
- MPAS_isAlarmRinging = ESMF_AlarmIsRinging(alarmPtr % a, rc=ierr)
+ if (alarmPtr % isSet) then
+ if (MPAS_inRingingEnvelope(clock, alarmPtr, interval, ierr)) then
+ MPAS_isAlarmRinging = .true.
+ end if
end if
- if (present(ierr)) then
- if (ierr == ESMF_SUCCESS) ierr = 0
- end if
exit
end if
alarmPtr => alarmPtr % next
@@ -660,55 +605,134 @@
end function MPAS_isAlarmRinging
- subroutine MPAS_removeClockAlarm(clock, alarmID, ierr)
-! TODO: Actually remove the alarm from the list and decrement clock%nAlarms?
+ subroutine MPAS_getClockRingingAlarms(clock, nAlarms, alarmList, interval, ierr)
+
implicit none
- type (MPAS_Clock_type), intent(inout) :: clock
- integer, intent(in) :: alarmID
+ type (MPAS_Clock_type), intent(in) :: clock
+ integer, intent(out) :: nAlarms
+ integer, dimension(MPAS_MAX_ALARMS), intent(out) :: alarmList
+ type (MPAS_TimeInterval_type), intent(in), optional :: interval
integer, intent(out), optional :: ierr
type (MPAS_Alarm_type), pointer :: alarmPtr
- write(0,*) 'Called MPAS_removeClockAlarm'
+ write(0,*) 'Called MPAS_getClockRingingAlarms'
if (present(ierr)) ierr = 0
+ nAlarms = 0
+
alarmPtr => clock % alarmListHead
do while (associated(alarmPtr))
- if (alarmPtr % alarmID == alarmID) then
- call ESMF_AlarmDisable(alarmPtr % a, rc=ierr)
- if (present(ierr)) then
- if (ierr == ESMF_SUCCESS) ierr = 0
+ if (alarmPtr % isSet) then
+ if (MPAS_inRingingEnvelope(clock, alarmPtr, interval, ierr)) then
+ nAlarms = nAlarms + 1
+ alarmList(nAlarms) = alarmPtr % alarmID
end if
- exit
end if
alarmPtr => alarmPtr % next
end do
- end subroutine MPAS_removeClockAlarm
+ end subroutine MPAS_getClockRingingAlarms
- subroutine MPAS_resetClockAlarm(clock, alarmID, ierr)
+ logical function MPAS_inRingingEnvelope(clock, alarmPtr, interval, ierr)
implicit none
+
+ type (MPAS_Clock_type), intent(in) :: clock
+ type (MPAS_Alarm_type), pointer, intent(in) :: alarmPtr
+ type (MPAS_TimeInterval_type), intent(in), optional :: interval
+ integer, intent(out), optional :: ierr
+
+ type (MPAS_Time_type) :: alarmNow
+ type (MPAS_Time_type) :: alarmThreshold
+ alarmNow = MPAS_getClockTime(clock, MPAS_NOW, ierr)
+ alarmThreshold = alarmPtr % ringTime
+
+ MPAS_inRingingEnvelope = .false.
+
+ if(clock % direction == MPAS_FORWARD) then
+
+ if (present(interval)) then
+ alarmNow = alarmNow + interval;
+ end if
+
+ if (alarmPtr % isRecurring) then
+ alarmThreshold = alarmPtr % prevRingTime + alarmPtr % ringTimeInterval
+ end if
+
+ if (alarmThreshold <= alarmNow) then
+ MPAS_inRingingEnvelope = .true.
+ end if
+ else
+
+ if (present(interval)) then
+ alarmNow = alarmNow - interval;
+ end if
+
+ if (alarmPtr % isRecurring) then
+ alarmThreshold = alarmPtr % prevRingTime - alarmPtr % ringTimeInterval
+ end if
+
+ if (alarmThreshold >= alarmNow) then
+ MPAS_inRingingEnvelope = .true.
+ end if
+ end if
+
+ end function MPAS_inRingingEnvelope
+
+
+
+ subroutine MPAS_resetClockAlarm(clock, alarmID, interval, ierr)
+
+ implicit none
+
type (MPAS_Clock_type), intent(inout) :: clock
integer, intent(in) :: alarmID
+ type (MPAS_TimeInterval_type), intent(in), optional :: interval
integer, intent(out), optional :: ierr
+ type (MPAS_Time_type) :: alarmNow
type (MPAS_Alarm_type), pointer :: alarmPtr
- type (ESMF_Time) :: ringTime
write(0,*) 'Called MPAS_resetClockAlarm'
if (present(ierr)) ierr = 0
alarmPtr => clock % alarmListHead
do while (associated(alarmPtr))
+
if (alarmPtr % alarmID == alarmID) then
- call ESMF_AlarmRingerOff(alarmPtr % a, rc=ierr)
- if (present(ierr)) then
- if (ierr == ESMF_SUCCESS) ierr = 0
+
+ if (MPAS_inRingingEnvelope(clock, alarmPtr, interval, ierr)) then
+
+ if (.not. alarmPtr % isRecurring) then
+ alarmPtr % isSet = .false.
+ else
+ alarmNow = MPAS_getClockTime(clock, MPAS_NOW, ierr)
+
+ if(clock % direction == MPAS_FORWARD) then
+ if (present(interval)) then
+ alarmNow = alarmNow + interval
+ end if
+
+ do while(alarmPtr % prevRingTime <= alarmNow)
+ alarmPtr % prevRingTime = alarmPtr % prevRingTime + alarmPtr % ringTimeInterval
+ end do
+ alarmPtr % prevRingTime = alarmPtr % prevRingTime - alarmPtr % ringTimeInterval
+ else
+ if (present(interval)) then
+ alarmNow = alarmNow - interval
+ end if
+
+ do while(alarmPtr % prevRingTime >= alarmNow)
+ alarmPtr % prevRingTime = alarmPtr % prevRingTime - alarmPtr % ringTimeInterval
+ end do
+ alarmPtr % prevRingTime = alarmPtr % prevRingTime + alarmPtr % ringTimeInterval
+ end if
+ end if
end if
exit
end if
@@ -718,86 +742,80 @@
end subroutine MPAS_resetClockAlarm
- subroutine MPAS_getClockRingingAlarms(clock, nAlarms, alarmList, interval, ierr)
-! TODO: check for alarms ringing within the specified interval rather than just now
+ ! specify a valid previousRingTime for each alarm
+ subroutine MPAS_CalibrateAlarms(clock, ierr)
+
implicit none
- type (MPAS_Clock_type), intent(inout) :: clock ! BETTER IF INTENT(IN)
- integer, intent(out) :: nAlarms
- integer, dimension(MPAS_MAX_ALARMS), intent(out) :: alarmList
- type (MPAS_TimeInterval_type), intent(in), optional :: interval
+ type (MPAS_Clock_type), intent(in) :: clock
integer, intent(out), optional :: ierr
+ type (MPAS_Time_type) :: now
+ type (MPAS_Time_type) :: previousRingTime
+ type (MPAS_Time_type) :: negativeNeighborRingTime
+ type (MPAS_Time_type) :: positiveNeighborRingTime
+ type (MPAS_TimeInterval_type) :: ringTimeInterval
type (MPAS_Alarm_type), pointer :: alarmPtr
- type (ESMF_TimeInterval) :: timeStep
- type (MPAS_TimeInterval_type) :: userInterval
- write(0,*) 'Called MPAS_getClockRingingAlarms'
- if (present(ierr)) ierr = 0
+ now = MPAS_getClockTime(clock, MPAS_NOW, ierr)
+
+ alarmPtr => clock % alarmListHead
+ do while (associated(alarmPtr))
+
+ if (.not. alarmPtr % isRecurring) then
+ alarmPtr % isSet = .true.
+ else
+
+ previousRingTime = alarmPtr % prevRingTime
- if (present(interval)) then
- userInterval = interval
- call ESMF_ClockGet(clock % c, TimeStep=timeStep, rc=ierr)
- call ESMF_ClockSet(clock % c, TimeStep=userInterval % ti, rc=ierr)
- call ESMF_ClockAdvance(clock % c, rc=ierr)
- nAlarms = 0
- alarmPtr => clock % alarmListHead
- do while (associated(alarmPtr))
- if (ESMF_AlarmIsRinging(alarmPtr % a, rc=ierr)) then
- if (present(ierr)) then
- if (ierr == ESMF_SUCCESS) ierr = 0
- end if
- nAlarms = nAlarms + 1
- alarmList(nAlarms) = alarmPtr % alarmID
+ if (previousRingTime <= now) then
+
+ do while(previousRingTime <= now)
+ previousRingTime = previousRingTime + alarmPtr % ringTimeInterval
+ end do
+ positiveNeighborRingTime = previousRingTime
+
+ do while(previousRingTime >= now)
+ previousRingTime = previousRingTime - alarmPtr % ringTimeInterval
+ end do
+ negativeNeighborRingTime = previousRingTime
+
+ else
+
+ do while(previousRingTime >= now)
+ previousRingTime = previousRingTime - alarmPtr % ringTimeInterval
+ end do
+ negativeNeighborRingTime = previousRingTime
+
+ do while(previousRingTime <= now)
+ previousRingTime = previousRingTime + alarmPtr % ringTimeInterval
+ end do
+ positiveNeighborRingTime = previousRingTime
+
end if
- alarmPtr => alarmPtr % next
- end do
- userInterval = -userInterval
- call ESMF_ClockSet(clock % c, TimeStep=userInterval % ti, rc=ierr)
- call ESMF_ClockAdvance(clock % c, rc=ierr)
- call ESMF_ClockSet(clock % c, TimeStep=timeStep, rc=ierr)
-! TODO: Do the operations in this loop only for alarms that were not already ringing?
- alarmPtr => clock % alarmListHead
- do while (associated(alarmPtr))
- if (ESMF_AlarmIsRinging(alarmPtr % a, rc=ierr)) then
- call ESMF_AlarmRingerOff(alarmPtr % a, rc=ierr)
- if (alarmPtr % recurring) then
- call ESMF_AlarmSet(alarmPtr % a, &
- RingTime=alarmPtr%RingTime, &
- RingInterval=alarmPtr%RingTimeInterval, &
- Enabled=.true., rc=ierr)
- else
- call ESMF_AlarmSet(alarmPtr % a, &
- RingTime=alarmPtr%RingTime, &
- Enabled=.true., rc=ierr)
- end if
- if (present(ierr)) then
- if (ierr == ESMF_SUCCESS) ierr = 0
- end if
+
+ if (clock % direction == MPAS_FORWARD) then
+ alarmPtr % prevRingTime = negativeNeighborRingTime
+ else
+ alarmPtr % prevRingTime = positiveNeighborRingTime
end if
- alarmPtr => alarmPtr % next
- end do
- else
- nAlarms = 0
- alarmPtr => clock % alarmListHead
- do while (associated(alarmPtr))
- if (ESMF_AlarmIsRinging(alarmPtr % a, rc=ierr)) then
- if (present(ierr)) then
- if (ierr == ESMF_SUCCESS) ierr = 0
- end if
- nAlarms = nAlarms + 1
- alarmList(nAlarms) = alarmPtr % alarmID
- end if
- alarmPtr => alarmPtr % next
- end do
+
+ end if
+
+ alarmPtr => alarmPtr % next
+
+ end do
+
+ if (present(ierr)) then
+ if (ierr == ESMF_SUCCESS) ierr = 0
end if
+
+ end subroutine MPAS_CalibrateAlarms
- end subroutine MPAS_getClockRingingAlarms
+ subroutine MPAS_setTime(curr_time, YYYY, MM, DD, DoY, H, M, S, S_n, S_d, dateTimeString, ierr)
- subroutine MPAS_setTime(curr_time, YYYY, MM, DD, DoY, H, M, S, S_n, S_d, dateString, ierr)
-
implicit none
type (MPAS_Time_type), intent(out) :: curr_time
@@ -810,53 +828,143 @@
integer, intent(in), optional :: S
integer, intent(in), optional :: S_n
integer, intent(in), optional :: S_d
- character (len=*), intent(in), optional :: dateString
+ character (len=*), intent(in), optional :: dateTimeString
integer, intent(out), optional :: ierr
- integer :: month, day
+ integer, parameter :: integerMaxDigits = 8
+ integer :: year, month, day, hour, min, sec
+ integer :: numerator, denominator, denominatorPower
+ character (len=50) :: dateTimeString_
+ character (len=50) :: dateSubString
+ character (len=50) :: timeSubString
+ character (len=50) :: secDecSubString
+ character(len=50), pointer, dimension(:) :: subStrings
+
write(0,*) 'Called MPAS_setTime'
- if (present(DoY)) then
- call getMonthDay(YYYY, DoY, month, day)
-
- ! consistency check
- if (present(MM)) then
- if (MM /= month) then
- if (present(ierr)) ierr = 1
- write(0,*) 'ERROR: MPAS_setTime : DoY and MM are inconsistent - using DoY'
+ if (present(dateTimeString)) then
+
+ dateTimeString_ = dateTimeString
+ numerator = 0
+ denominator = 1
+
+ call SplitString(dateTimeString_, ".", subStrings)
+ if (size(subStrings) == 2) then ! contains second decimals
+ dateTimeString_ = subStrings(1)
+ secDecSubString = subStrings(2)(:integerMaxDigits)
+ deallocate(subStrings)
+ denominatorPower = len_trim(secDecSubString)
+ if(denominatorPower > 0) then
+ read(secDecSubString,*) numerator
+ if(numerator > 0) then
+ denominator = 10**denominatorPower
+ end if
end if
+ else if (size(subStrings) /= 1) then
+ deallocate(subStrings)
+ if (present(ierr)) ierr = 1
+ write(0,*) 'ERROR: Invalid DateTime string', dateTimeString
+ return
end if
- if (present(DD)) then
- if (DD /= day) then
+
+ call SplitString(dateTimeString_, "_", subStrings)
+
+ if(size(subStrings) == 2) then ! contains a date and time
+ dateSubString = subStrings(1)
+ timeSubString = subStrings(2)
+ deallocate(subStrings)
+
+ call SplitString(timeSubString, ":", subStrings)
+
+ if (size(subStrings) == 3) then
+ read(subStrings(1),*) hour
+ read(subStrings(2),*) min
+ read(subStrings(3),*) sec
+ deallocate(subStrings)
+ else
+ deallocate(subStrings)
if (present(ierr)) ierr = 1
- write(0,*) 'ERROR: MPAS_setTime : DoY and DD are inconsistent - using DoY'
+ write(0,*) 'ERROR: Invalid DateTime string (invalid time substring)', dateTimeString
+ return
end if
- end if
- else
- if (present(MM)) then
- month = MM
+
+ else if(size(subStrings) == 1) then ! contains only a date- assume all time values are 0
+ dateSubString = subStrings(1)
+ deallocate(subStrings)
+
+ hour = 0
+ min = 0
+ sec = 0
+
else
+ deallocate(subStrings)
if (present(ierr)) ierr = 1
- write(0,*) 'ERROR: MPAS_setTime : Neither DoY nor MM are specified'
+ write(0,*) 'ERROR: Invalid DateTime string', dateTimeString
return
end if
- if (present(DD)) then
- day = DD
+ call SplitString(dateSubString, "-", subStrings)
+
+ if (size(subStrings) == 3) then
+ read(subStrings(1),*) year
+ read(subStrings(2),*) month
+ read(subStrings(3),*) day
+ deallocate(subStrings)
else
+ deallocate(subStrings)
if (present(ierr)) ierr = 1
- write(0,*) 'ERROR: MPAS_setTime : Neither DoY nor DD are specified'
+ write(0,*) 'ERROR: Invalid DateTime string (invalid date substring)', dateTimeString
return
end if
- end if
- if (.not. isValidDate(YYYY,month,day)) then
- write(0,*) 'ERROR: MPAS_setTime : Invalid date'
- return
+ call ESMF_TimeSet(curr_time % t, YY=year, MM=month, DD=day, H=hour, M=min, S=sec, Sn=numerator, Sd=denominator, rc=ierr)
+
+ else
+
+ if (present(DoY)) then
+ call getMonthDay(YYYY, DoY, month, day)
+
+ ! consistency check
+ if (present(MM)) then
+ if (MM /= month) then
+ if (present(ierr)) ierr = 1
+ write(0,*) 'ERROR: MPAS_setTime : DoY and MM are inconsistent - using DoY'
+ end if
+ end if
+ if (present(DD)) then
+ if (DD /= day) then
+ if (present(ierr)) ierr = 1
+ write(0,*) 'ERROR: MPAS_setTime : DoY and DD are inconsistent - using DoY'
+ end if
+ end if
+ else
+ if (present(MM)) then
+ month = MM
+ else
+ if (present(ierr)) ierr = 1
+ write(0,*) 'ERROR: MPAS_setTime : Neither DoY nor MM are specified'
+ return
+ end if
+
+ if (present(DD)) then
+ day = DD
+ else
+ if (present(ierr)) ierr = 1
+ write(0,*) 'ERROR: MPAS_setTime : Neither DoY nor DD are specified'
+ return
+ end if
+ end if
+
+ if (.not. isValidDate(YYYY,month,day)) then
+ write(0,*) 'ERROR: MPAS_setTime : Invalid date'
+ return
+ end if
+
+ call ESMF_TimeSet(curr_time % t, YY=YYYY, MM=month, DD=day, H=H, M=M, S=S, Sn=S_n, Sd=S_d, rc=ierr)
+
end if
-
- call ESMF_TimeSet(curr_time % t, YY=YYYY, MM=month, DD=day, H=H, M=M, S=S, Sn=S_n, Sd=S_d, rc=ierr)
+
if (present(ierr)) then
if (ierr == ESMF_SUCCESS) ierr = 0
end if
@@ -864,7 +972,7 @@
end subroutine MPAS_setTime
- subroutine MPAS_getTime(curr_time, YYYY, MM, DD, DoY, H, M, S, S_n, S_d, dateString, ierr)
+ subroutine MPAS_getTime(curr_time, YYYY, MM, DD, DoY, H, M, S, S_n, S_d, dateTimeString, ierr)
implicit none
@@ -878,14 +986,14 @@
integer, intent(out), optional :: S
integer, intent(out), optional :: S_n
integer, intent(out), optional :: S_d
- character (len=32), intent(out), optional :: dateString
+ character (len=32), intent(out), optional :: dateTimeString
integer, intent(out), optional :: ierr
write(0,*) 'Called MPAS_getTime'
call ESMF_TimeGet(curr_time % t, YY=YYYY, MM=MM, DD=DD, H=H, M=M, S=S, Sn=S_n, Sd=S_d, rc=ierr)
call ESMF_TimeGet(curr_time % t, dayOfYear=DoY, rc=ierr)
- call ESMF_TimeGet(curr_time % t, timeString=dateString, rc=ierr)
+ call ESMF_TimeGet(curr_time % t, timeString=dateTimeString, rc=ierr)
if (present(ierr)) then
if (ierr == ESMF_SUCCESS) ierr = 0
end if
@@ -893,9 +1001,8 @@
end subroutine MPAS_getTime
- subroutine MPAS_setTimeInterval(interval, DD, H, M, S, S_n, S_d, timeString, ierr)
+ subroutine MPAS_setTimeInterval(interval, DD, H, M, S, S_n, S_d, timeString, dt, ierr)
! TODO: add double-precision seconds
-! TODO: support timeString
implicit none
@@ -907,10 +1014,21 @@
integer, intent(in), optional :: S_n
integer, intent(in), optional :: S_d
character (len=*), intent(in), optional :: timeString
+ real (kind=RKIND), intent(in), optional :: dt
integer, intent(out), optional :: ierr
+ integer, parameter :: integerMaxDigits = 8
integer :: days, hours, minutes, seconds
+ integer :: numerator, denominator, denominatorPower
+ type (MPAS_TimeInterval_type) :: zeroInterval
+ integer :: day, hour, min, sec
+ character (len=50) :: timeString_
+ character (len=50) :: daySubString
+ character (len=50) :: timeSubString
+ character (len=50) :: secDecSubString
+ character(len=50), pointer, dimension(:) :: subStrings
+
write(0,*) 'Called MPAS_setTimeInterval'
! if (present(DD)) then
@@ -976,11 +1094,95 @@
! seconds = seconds + hours*3600 + minutes*60
! call ESMF_TimeIntervalSet(interval % ti, D=days, S=seconds, Sn=S_n, Sd=S_d, rc=ierr)
- call ESMF_TimeIntervalSet(interval % ti, D=DD, H=H, M=M, S=S, Sn=S_n, Sd=S_d, rc=ierr)
+
+
+ if (present(timeString) .or. present(dt)) then
+
+
+ if(present(dt)) then
+ write (timeString_,*) "00:00:", dt
+ else
+ timeString_ = timeString
+ end if
+
+ numerator = 0
+ denominator = 1
+
+ call SplitString(timeString_, ".", subStrings)
+
+ if (size(subStrings) == 2) then ! contains second decimals
+ timeString_ = subStrings(1)
+ secDecSubString = subStrings(2)(:integerMaxDigits)
+ deallocate(subStrings)
+
+ denominatorPower = len_trim(secDecSubString)
+ if(denominatorPower > 0) then
+ read(secDecSubString,*) numerator
+ if(numerator > 0) then
+ denominator = 10**denominatorPower
+ end if
+ end if
+ else if (size(subStrings) /= 1) then
+ deallocate(subStrings)
+ if (present(ierr)) ierr = 1
+ write(0,*) 'ERROR: Invalid TimeInterval string', timeString
+ return
+ end if
+
+ call SplitString(timeString_, "_", subStrings)
+
+ if(size(subStrings) == 2) then ! contains a day and time
+ daySubString = subStrings(1)
+ timeSubString = subStrings(2)
+ deallocate(subStrings)
+ read(daySubString,*) day
+ else if(size(subStrings) == 1) then ! contains only a time- assume day is 0
+ timeSubString = subStrings(1)
+ deallocate(subStrings)
+ day = 0
+ else
+ deallocate(subStrings)
+ if (present(ierr)) ierr = 1
+ write(0,*) 'ERROR: Invalid TimeInterval string', timeString
+ return
+ end if
+
+ call SplitString(timeSubString, ":", subStrings)
+
+ if (size(subStrings) == 3) then
+ read(subStrings(1),*) hour
+ read(subStrings(2),*) min
+ read(subStrings(3),*) sec
+ deallocate(subStrings)
+ else
+ deallocate(subStrings)
+ if (present(ierr)) ierr = 1
+ write(0,*) 'ERROR: Invalid TimeInterval string (invalid time substring)', timeString
+ return
+ end if
+
+ call ESMF_TimeIntervalSet(interval % ti, D=day, H=hour, M=min, S=sec, Sn=numerator, Sd=denominator, rc=ierr)
+
+ else
+
+ call ESMF_TimeIntervalSet(interval % ti, D=DD, H=H, M=M, S=S, Sn=S_n, Sd=S_d, rc=ierr)
+
+ end if
+
+ ! verify that time interval is positive
+ call ESMF_TimeIntervalSet(zeroInterval % ti, D=0, H=0, M=0, S=0, rc=ierr)
+
if (present(ierr)) then
if (ierr == ESMF_SUCCESS) ierr = 0
end if
+ if (interval <= zeroInterval) then
+ if (present(ierr)) ierr = 1
+ write(0,*) 'ERROR: TimeInterval must be greater than 0', timeString !'ERROR: TimeInterval cannot be negative'
+ end if
+
+
+
end subroutine MPAS_setTimeInterval
@@ -1290,6 +1492,39 @@
! end function mod
+ subroutine SplitString(string, delimiter, subStrings)
+
+ implicit none
+
+ character(len=*), intent(in) :: string
+ character, intent(in) :: delimiter
+ character(len=*), pointer, dimension(:) :: subStrings
+
+ integer :: i, start, index
+
+ index = 1
+ do i = 1, len(string)
+ if(string(i:i) == delimiter) then
+ index = index + 1
+ end if
+ end do
+
+ allocate(subStrings(1:index))
+
+ start = 1
+ index = 1
+ do i = 1, len(string)
+ if(string(i:i) == delimiter) then
+ subStrings(index) = string(start:i-1)
+ index = index + 1
+ start = i + 1
+ end if
+ end do
+ subStrings(index) = string(start:len(string))
+
+ end subroutine SplitString
+
+
subroutine getMonthDay(YYYY, DoY, month, day)
implicit none
@@ -1376,9 +1611,14 @@
end function isLeapYear
+
+
+
+
end module mpas_timekeeping
+
subroutine wrf_error_fatal(msg)
implicit none
</font>
</pre>