Line data Source code
1 : module time_manager
2 :
3 : ! Provide CAM specific time management. This is a wrapper layer for the ESMF
4 : ! time manager utility.
5 :
6 : use ESMF
7 :
8 : use shr_kind_mod, only: r8 => shr_kind_r8, SHR_KIND_CS
9 : use shr_cal_mod, only: shr_cal_noleap, shr_cal_gregorian
10 : use spmd_utils, only: masterproc
11 : use string_utils, only: to_upper
12 : use cam_abortutils, only: endrun
13 : use cam_logfile, only: iulog
14 :
15 : implicit none
16 : private
17 : save
18 :
19 : ! Public methods
20 :
21 : public ::&
22 : timemgr_init, &! time manager initialization
23 : advance_timestep, &! increment the clocks current time
24 : get_step_size, &! return step size in seconds
25 : get_nstep, &! return timestep number
26 : get_curr_date, &! return date components at end of current timestep
27 : get_prev_date, &! return date components at beginning of current timestep
28 : get_start_date, &! return components of the start date
29 : get_stop_date, &! return components of the stop date
30 : get_run_duration, &! return run duration in whole days and remaining seconds
31 : get_ref_date, &! return components of the reference date
32 : get_perp_date, &! return components of the perpetual date, and current time of day
33 : get_curr_time, &! return components of elapsed time since reference date at end of current timestep
34 : get_prev_time, &! return components of elapsed time since reference date at beg of current timestep
35 : get_curr_calday, &! return calendar day at end of current timestep
36 : get_julday, &! return julian day from input date, time
37 : get_calday, &! return calendar day from input date
38 : is_first_step, &! return true on first step of initial run
39 : is_first_restart_step, &! return true on first step of restart or branch run
40 : timemgr_is_caltype, &! return true if incoming calendar type string matches actual calendar type in use
41 : timemgr_get_calendar_cf, &! return cf standard for calendar type
42 : is_end_curr_day, &! return true on last timestep in current day
43 : is_end_curr_month, &! return true on last timestep in current month
44 : is_last_step, &! return true on last timestep
45 : is_perpetual, &! return true if perpetual calendar is in use
46 : timemgr_datediff, &! calculate difference between two time instants
47 : timemgr_time_ge, &! check if time2 is later than or equal to time1
48 : timemgr_time_inc, &! increment time instant by a given interval
49 : timemgr_set_date_time, &! set the current date and time
50 : set_time_float_from_date, &! returns a float representation of time given yr, mon, day, sec
51 : set_date_from_time_float ! returns yr, mon, day, sec given time float
52 :
53 : public :: is_leapyear
54 :
55 : ! Private module data
56 :
57 : integer, parameter :: uninit_int = -999999999
58 :
59 : integer :: dtime = uninit_int ! timestep in seconds
60 :
61 : character(len=32) :: calendar ! Calendar type
62 : logical :: tm_first_restart_step = .false. ! true for first step of a restart or branch run
63 : logical :: tm_perp_calendar = .false. ! true when using perpetual calendar
64 : integer :: cal_type = uninit_int ! calendar type
65 :
66 : ! The target attribute for tm_cal is needed (at least by NAG) because there are
67 : ! pointers to this object inside ESMF_Time objects.
68 : type(ESMF_Calendar), target :: tm_cal ! calendar
69 : type(ESMF_Clock) :: tm_clock ! Model clock
70 : type(ESMF_Time) :: tm_perp_date ! perpetual date
71 :
72 : !=========================================================================================
73 : contains
74 : !=========================================================================================
75 :
76 1536 : subroutine timemgr_init( &
77 : dtime_in, calendar_in, start_ymd, start_tod, ref_ymd, &
78 : ref_tod, stop_ymd, stop_tod, curr_ymd, curr_tod, &
79 : perpetual_run, perpetual_ymd, initial_run)
80 :
81 : ! Initialize the time manager.
82 :
83 : ! Arguments
84 : integer, intent(in) :: dtime_in ! Coupling period (sec)
85 : character(len=*), intent(IN) :: calendar_in ! Calendar type
86 : integer, intent(IN) :: start_ymd ! Start date (YYYYMMDD)
87 : integer, intent(IN) :: start_tod ! Start time of day (sec)
88 : integer, intent(IN) :: ref_ymd ! Reference date (YYYYMMDD)
89 : integer, intent(IN) :: ref_tod ! Reference time of day (sec)
90 : integer, intent(IN) :: stop_ymd ! Stop date (YYYYMMDD)
91 : integer, intent(IN) :: stop_tod ! Stop time of day (sec)
92 : integer, intent(IN) :: curr_ymd ! current date (YYYYMMDD)
93 : integer, intent(IN) :: curr_tod ! current time of day (sec)
94 : logical, intent(IN) :: perpetual_run ! If in perpetual mode or not
95 : integer, intent(IN) :: perpetual_ymd ! Perpetual date (YYYYMMDD)
96 : logical, intent(in) :: initial_run ! true => initial (or startup) run
97 :
98 : ! Local variables
99 : character(len=*), parameter :: sub = 'timemgr_init'
100 : integer :: rc ! return code
101 : type(ESMF_Time) :: start_date ! start date for run
102 : type(ESMF_Time) :: stop_date ! stop date for run
103 : type(ESMF_Time) :: curr_date ! temporary date used in logic
104 : type(ESMF_Time) :: ref_date ! reference date for time coordinate
105 : !----------------------------------------------------------------------------------------
106 :
107 1536 : dtime = dtime_in
108 :
109 1536 : calendar = trim(calendar_in)
110 1536 : call init_calendar()
111 :
112 : ! create ESMF time instant objects
113 1536 : start_date = TimeSetymd(start_ymd, start_tod, "start_date")
114 1536 : stop_date = TimeSetymd(stop_ymd, stop_tod, "stop_date")
115 1536 : ref_date = TimeSetymd(ref_ymd, ref_tod, "ref_date")
116 1536 : curr_date = TimeSetymd(curr_ymd, curr_tod, "curr_date")
117 :
118 : ! In order that an initial run start with nstep=0 (which is the criteria
119 : ! for the is_first_step() function to return true), the current time
120 : ! must be the same as the start time. To allow the driver to be doing a
121 : ! continue run and at the same time force CAM into an initial run mode
122 : ! this code forces the start time to equal the current time, even though
123 : ! that may not be true for the data received from the driver.
124 1536 : if (initial_run) then
125 768 : start_date = curr_date
126 : end if
127 :
128 : ! Initialize ESMF clock
129 1536 : call initialize_clock(start_date, ref_date, curr_date, stop_date)
130 :
131 1536 : if (.not. initial_run) then
132 :
133 : ! Advance the timestep. Data from the restart file corresponds to the
134 : ! last timestep of the previous run.
135 768 : call advance_timestep()
136 768 : tm_first_restart_step = .true.
137 : end if
138 :
139 : ! Initialize date used for perpetual calendar day calculation.
140 1536 : if (perpetual_run) then
141 0 : tm_perp_calendar = .true.
142 0 : tm_perp_date = TimeSetymd(perpetual_ymd, 0, "tm_perp_date")
143 : end if
144 :
145 : ! Print configuration summary to log file (stdout).
146 1536 : if (masterproc) then
147 2 : call timemgr_print()
148 : end if
149 :
150 38400 : end subroutine timemgr_init
151 :
152 : !=========================================================================================
153 :
154 1536 : subroutine initialize_clock( start_date, ref_date, curr_date, stop_date )
155 :
156 : ! Create an ESMF clock based on the stepsize, start_date, stop_date, and ref_date
157 : ! Then advance the clock to the curr_date.
158 :
159 : ! Input variables
160 : type(ESMF_Time), intent(inout) :: start_date ! start date for run
161 : type(ESMF_Time), intent(inout) :: ref_date ! reference date for time coordinate
162 : type(ESMF_Time), intent(inout) :: curr_date ! current date (equal to start_date)
163 : type(ESMF_Time), intent(inout) :: stop_date ! stop date for run
164 :
165 : ! Local variables
166 : character(len=*), parameter :: sub = 'initialize_clock'
167 : type(ESMF_TimeInterval) :: step_size ! timestep size
168 : type(ESMF_Time) :: current ! current date (from clock)
169 : integer :: yr, mon, day, tod ! Year, month, day, and second as integers
170 : integer :: rc ! return code
171 :
172 1536 : if ( mod(86400,dtime) /= 0 ) then
173 0 : call endrun (sub//': timestep must divide evenly into 1 day')
174 : end if
175 :
176 1536 : call ESMF_TimeIntervalSet(step_size, s=dtime, rc=rc)
177 1536 : call chkrc(rc, sub//': error return from ESMF_TimeIntervalSet: setting step_size')
178 :
179 : ! check for valid input
180 1536 : if ( stop_date <= start_date ) then
181 0 : write(iulog,*)sub, ': stop date must be specified later than start date: '
182 0 : call ESMF_TimeGet( start_date, yy=yr, mm=mon, dd=day, s=tod )
183 0 : write(iulog,*) ' Start date (yr, mon, day, tod): ', yr, mon, day, tod
184 0 : call ESMF_TimeGet( stop_date, yy=yr, mm=mon, dd=day, s=tod )
185 0 : write(iulog,*) ' Stop date (yr, mon, day, tod): ', yr, mon, day, tod
186 0 : call endrun
187 : end if
188 1536 : if ( curr_date >= stop_date ) then
189 0 : write(iulog,*)sub, ': stop date must be specified later than current date: '
190 0 : call ESMF_TimeGet( curr_date, yy=yr, mm=mon, dd=day, s=tod )
191 0 : write(iulog,*) ' Current date (yr, mon, day, tod): ', yr, mon, day, tod
192 0 : call ESMF_TimeGet( stop_date, yy=yr, mm=mon, dd=day, s=tod )
193 0 : write(iulog,*) ' Stop date (yr, mon, day, tod): ', yr, mon, day, tod
194 0 : call endrun
195 : end if
196 :
197 : ! Initialize the clock
198 : tm_clock = ESMF_ClockCreate(name="CAM Time-manager clock", timeStep=step_size, startTime=start_date, &
199 1536 : stopTime=stop_date, refTime=ref_date, rc=rc)
200 1536 : call chkrc(rc, sub//': error return from ESMF_ClockSetup')
201 :
202 : ! Advance clock to the current time (in case of a branch or restart)
203 1536 : call ESMF_ClockGet(tm_clock, currTime=current, rc=rc )
204 1536 : call chkrc(rc, sub//': error return from ESMF_ClockGet')
205 185856 : do while( curr_date > current )
206 184320 : call ESMF_ClockAdvance( tm_clock, rc=rc )
207 184320 : call chkrc(rc, sub//': error return from ESMF_ClockAdvance')
208 184320 : call ESMF_ClockGet(tm_clock, currTime=current )
209 184320 : call chkrc(rc, sub//': error return from ESMF_ClockGet')
210 : end do
211 :
212 39936 : end subroutine initialize_clock
213 :
214 : !=========================================================================================
215 :
216 18019008 : function TimeSetymd( ymd, tod, desc )
217 : !
218 : ! Set the time by an integer as YYYYMMDD and integer seconds in the day
219 : !
220 : integer, intent(in) :: ymd ! Year, month, day YYYYMMDD
221 : integer, intent(in) :: tod ! Time of day in seconds
222 : character(len=*), intent(in) :: desc ! Description of time to set
223 :
224 : type(ESMF_Time) :: TimeSetymd ! Return value
225 :
226 : character(len=*), parameter :: sub = 'TimeSetymd'
227 : integer :: yr, mon, day ! Year, month, day as integers
228 : integer :: rc ! return code
229 :
230 18019008 : if ( (ymd < 0) .or. (tod < 0) .or. (tod > 24*3600) )then
231 0 : write(iulog,*) sub//': error yymmdd is a negative number or time-of-day out of bounds', &
232 0 : ymd, tod
233 0 : call endrun
234 : end if
235 18019008 : yr = ymd / 10000
236 18019008 : mon = (ymd - yr*10000) / 100
237 18019008 : day = ymd - yr*10000 - mon*100
238 : call ESMF_TimeSet( TimeSetymd, yy=yr, mm=mon, dd=day, s=tod, &
239 18019008 : calendar=tm_cal, rc=rc)
240 18019008 : call chkrc(rc, sub//': error return from ESMF_TimeSet: setting '//trim(desc))
241 126133056 : end function TimeSetymd
242 :
243 : !=========================================================================================
244 :
245 485614080 : subroutine set_time_float_from_date( time, year, month, day, sec )
246 : !
247 : ! Set the time as a float given year, month, day, sec
248 : !
249 : implicit none
250 :
251 : real(r8),intent(out):: time
252 : integer, intent(in) :: year
253 : integer, intent(in) :: month
254 : integer, intent(in) :: day
255 : integer, intent(in) :: sec
256 :
257 : integer :: rc ! return code
258 : character(len=*), parameter :: sub = 'set_time_float_from_date'
259 : type(ESMF_Time) :: date, ref_date
260 : type(ESMF_TimeInterval) :: diff
261 : integer :: useday
262 :
263 : if ( ((calendar==shr_cal_noleap).or.(.not.is_leapyear(year))) &
264 485614080 : .and. (month==2) .and. (day==29) ) then
265 : ! set day to 28 when the calendar / year does not have a leap day
266 167424 : useday = 28
267 : else
268 485446656 : useday = day
269 : endif
270 :
271 485614080 : call ESMF_TimeSet( date, yy=year, mm=month, dd=useday, s=sec, calendar=tm_cal, rc=rc)
272 :
273 485614080 : if ( rc .ne. ESMF_SUCCESS ) then
274 0 : call chkrc(rc, sub//': error return from ESMF_TimeSet for set_time_float_from_date')
275 : endif
276 :
277 485614080 : call ESMF_ClockGet(tm_clock, refTime=ref_date, rc=rc )
278 485614080 : call chkrc(rc, sub//': error return from ESMF_ClockGet for set_time_float_from_date')
279 :
280 485614080 : diff = date - ref_date
281 :
282 485614080 : call ESMF_TimeIntervalGet( diff, d_r8=time, rc=rc)
283 485614080 : call chkrc(rc, sub//': error return from ESMF_TimeIntervalGet for set_time_float_from_date')
284 :
285 15539650560 : endsubroutine set_time_float_from_date
286 :
287 : !=========================================================================================
288 :
289 775680 : subroutine set_date_from_time_float( time, year, month, day, sec )
290 : !
291 : ! Set year, month, day, sec given the time as a float
292 : !
293 : implicit none
294 :
295 : real(r8),intent(in) :: time
296 : integer, intent(out) :: year
297 : integer, intent(out) :: month
298 : integer, intent(out) :: day
299 : integer, intent(out) :: sec
300 :
301 : integer :: rc ! return code
302 : character(len=*), parameter :: sub = 'set_date_from_time_float'
303 : type(ESMF_Time) :: date, ref_date
304 : type(ESMF_TimeInterval) :: diff
305 :
306 775680 : call ESMF_ClockGet(tm_clock, refTime=ref_date, rc=rc )
307 775680 : call chkrc(rc, sub//': error return from ESMF_ClockGet for rset_date_from_time_float')
308 :
309 775680 : call ESMF_TimeIntervalSet( diff, d_r8=time, rc=rc)
310 :
311 775680 : call chkrc(rc, sub//': error return from ESMF_TimeIntervalSet for set_date_from_time_float')
312 :
313 775680 : date = ref_date + diff
314 :
315 775680 : call ESMF_TimeGet( date, yy=year, mm=month, dd=day, s=sec, rc=rc)
316 775680 : call chkrc(rc, sub//': error return from ESMF_TimeGet for set_date_from_time_float')
317 :
318 24821760 : endsubroutine set_date_from_time_float
319 :
320 : !=========================================================================================
321 :
322 485614080 : logical function is_leapyear( yr )
323 : integer, intent(in) :: yr
324 485614080 : is_leapyear = (mod(yr, 400) == 0 .or. mod(yr,100) /= 0) .and. mod(yr,4)==0
325 485614080 : end function is_leapyear
326 :
327 :
328 : !=========================================================================================
329 :
330 : integer function TimeGetymd( date, tod )
331 : !
332 : ! Get the date and time of day in ymd from ESMF Time.
333 : !
334 : type(ESMF_Time), intent(inout) :: date ! Input date to convert to ymd
335 : integer, intent(out), optional :: tod ! Time of day in seconds
336 :
337 : character(len=*), parameter :: sub = 'TimeGetymd'
338 : integer :: yr, mon, day
339 : integer :: rc ! return code
340 :
341 : call ESMF_TimeGet( date, yy=yr, mm=mon, dd=day, rc=rc)
342 : call chkrc(rc, sub//': error return from ESMF_TimeGet')
343 : TimeGetymd = yr*10000 + mon*100 + day
344 : if ( present( tod ) )then
345 : call ESMF_TimeGet( date, yy=yr, mm=mon, dd=day, s=tod, rc=rc)
346 : call chkrc(rc, sub//': error return from ESMF_TimeGet')
347 : end if
348 : if ( yr < 0 )then
349 : write(iulog,*) sub//': error year is less than zero', yr
350 : call endrun
351 : end if
352 : end function TimeGetymd
353 :
354 : !=========================================================================================
355 :
356 0 : subroutine timemgr_set_date_time( new_ymd, new_tod )
357 :
358 : implicit none
359 :
360 : integer, intent(IN) :: new_ymd ! date (YYYYMMDD)
361 : integer, intent(IN) :: new_tod ! time of day (sec)
362 :
363 : type(ESMF_Time) :: new_time ! new time obj
364 : type(ESMF_Time) :: clk_time ! clock's time obj
365 : integer :: rc ! return code
366 :
367 : character(len=*), parameter :: sub = 'timemgr_set_date_time'
368 :
369 0 : new_time = TimeSetymd( new_ymd, new_tod, "curr_date" )
370 :
371 : ! Advance clock to the new time
372 :
373 0 : call ESMF_ClockGet(tm_clock, currTime=clk_time, rc=rc )
374 0 : call chkrc(rc, sub//': error return from ESMF_ClockGet')
375 0 : do while( new_time > clk_time )
376 0 : call ESMF_ClockAdvance( tm_clock, rc=rc )
377 0 : call chkrc(rc, sub//': error return from ESMF_ClockAdvance')
378 0 : call ESMF_ClockGet(tm_clock, currTime=clk_time )
379 0 : call chkrc(rc, sub//': error return from ESMF_ClockGet')
380 : end do
381 : ! Print configuration summary to log file (stdout).
382 :
383 0 : if (masterproc) then
384 0 : call timemgr_print()
385 : end if
386 :
387 0 : end subroutine timemgr_set_date_time
388 :
389 : !=========================================================================================
390 :
391 1536 : subroutine init_calendar( )
392 : !
393 : ! Initialize calendar
394 : !
395 : ! Local variables
396 : character(len=*), parameter :: sub = 'init_calendar'
397 : type(ESMF_CalKind_Flag) :: cal_type ! calendar type
398 : character(len=len(calendar)) :: caltmp
399 : integer :: rc ! return code
400 :
401 1536 : caltmp = to_upper(trim(calendar) )
402 1536 : if ( trim(caltmp) == trim(shr_cal_noleap) ) then
403 1536 : cal_type = ESMF_CALKIND_NOLEAP
404 0 : else if ( trim(caltmp) == trim(shr_cal_gregorian) ) then
405 0 : cal_type = ESMF_CALKIND_GREGORIAN
406 : else
407 0 : write(iulog,*)sub,': unrecognized calendar specified: ',calendar
408 0 : call endrun
409 : end if
410 1536 : tm_cal = ESMF_CalendarCreate( name=caltmp, calkindflag=cal_type, rc=rc )
411 1536 : call chkrc(rc, sub//': error return from ESMF_CalendarSet')
412 1536 : end subroutine init_calendar
413 :
414 : !=========================================================================================
415 :
416 2 : subroutine timemgr_print()
417 :
418 : ! Local variables
419 : character(len=*), parameter :: sub = 'timemgr_print'
420 : integer :: rc
421 : integer :: yr, mon, day
422 : integer ::&
423 : nstep = uninit_int, &! current step number
424 : step_sec = uninit_int, &! timestep size seconds
425 : start_yr = uninit_int, &! start year
426 : start_mon = uninit_int, &! start month
427 : start_day = uninit_int, &! start day of month
428 : start_tod = uninit_int, &! start time of day
429 : stop_yr = uninit_int, &! stop year
430 : stop_mon = uninit_int, &! stop month
431 : stop_day = uninit_int, &! stop day of month
432 : stop_tod = uninit_int, &! stop time of day
433 : ref_yr = uninit_int, &! reference year
434 : ref_mon = uninit_int, &! reference month
435 : ref_day = uninit_int, &! reference day of month
436 : ref_tod = uninit_int, &! reference time of day
437 : curr_yr = uninit_int, &! current year
438 : curr_mon = uninit_int, &! current month
439 : curr_day = uninit_int, &! current day of month
440 : curr_tod = uninit_int ! current time of day
441 : integer(ESMF_KIND_I8) :: step_no
442 : type(ESMF_Time) :: start_date! start date for run
443 : type(ESMF_Time) :: stop_date ! stop date for run
444 : type(ESMF_Time) :: curr_date ! current date for run
445 : type(ESMF_Time) :: ref_date ! reference date
446 : type(ESMF_TimeInterval) :: step ! Time-step
447 : !-----------------------------------------------------------------------------------------
448 :
449 : call ESMF_ClockGet( tm_clock, startTime=start_date, currTime=curr_date, &
450 : refTime=ref_date, stopTime=stop_date, timeStep=step, &
451 2 : advanceCount=step_no, rc=rc )
452 2 : call chkrc(rc, sub//': error return from ESMF_ClockGet')
453 2 : nstep = step_no
454 :
455 2 : write(iulog,*)' ********** Time Manager Configuration **********'
456 :
457 2 : call ESMF_TimeIntervalGet( step, s=step_sec, rc=rc )
458 2 : call chkrc(rc, sub//': error return from ESMF_TimeIntervalGet')
459 :
460 : call ESMF_TimeGet( start_date, yy=start_yr, mm=start_mon, dd=start_day, &
461 2 : s=start_tod, rc=rc )
462 2 : call chkrc(rc, sub//': error return from ESMF_TimeGet')
463 : call ESMF_TimeGet( stop_date, yy=stop_yr, mm=stop_mon, dd=stop_day, &
464 2 : s=stop_tod, rc=rc )
465 2 : call chkrc(rc, sub//': error return from ESMF_TimeGet')
466 : call ESMF_TimeGet( ref_date, yy=ref_yr, mm=ref_mon, dd=ref_day, s=ref_tod, &
467 2 : rc=rc )
468 2 : call chkrc(rc, sub//': error return from ESMF_TimeGet')
469 : call ESMF_TimeGet( curr_date, yy=curr_yr, mm=curr_mon, dd=curr_day, &
470 2 : s=curr_tod, rc=rc )
471 2 : call chkrc(rc, sub//': error return from ESMF_TimeGet')
472 :
473 2 : write(iulog,*)' Calendar type: ',trim(calendar)
474 2 : write(iulog,*)' Timestep size (seconds): ', step_sec
475 2 : write(iulog,*)' Start date (yr mon day tod): ', start_yr, start_mon, &
476 4 : start_day, start_tod
477 2 : write(iulog,*)' Stop date (yr mon day tod): ', stop_yr, stop_mon, &
478 4 : stop_day, stop_tod
479 2 : write(iulog,*)' Reference date (yr mon day tod): ', ref_yr, ref_mon, &
480 4 : ref_day, ref_tod
481 2 : write(iulog,*)' Current step number: ', nstep
482 2 : write(iulog,*)' Current date (yr mon day tod): ', curr_yr, curr_mon, &
483 4 : curr_day, curr_tod
484 :
485 2 : if ( tm_perp_calendar ) then
486 0 : call ESMF_TimeGet( tm_perp_date, yy=yr, mm=mon, dd=day, rc=rc )
487 0 : call chkrc(rc, sub//': error return from ESMF_TimeGet')
488 0 : write(iulog,*)' Use perpetual diurnal cycle date (yr mon day): ', &
489 0 : yr, mon, day
490 : end if
491 :
492 2 : write(iulog,*)' ************************************************'
493 :
494 88 : end subroutine timemgr_print
495 : !=========================================================================================
496 :
497 370176 : subroutine advance_timestep()
498 :
499 : ! Increment the timestep number.
500 :
501 : ! Local variables
502 : character(len=*), parameter :: sub = 'advance_timestep'
503 : integer :: rc
504 : !-----------------------------------------------------------------------------------------
505 :
506 370176 : call ESMF_ClockAdvance( tm_clock, rc=rc )
507 370176 : call chkrc(rc, sub//': error return from ESMF_ClockAdvance')
508 :
509 : ! Set first step flag off.
510 :
511 370176 : tm_first_restart_step = .false.
512 :
513 370176 : end subroutine advance_timestep
514 : !=========================================================================================
515 :
516 19610162 : integer function get_step_size()
517 :
518 : ! Return the step size in seconds.
519 :
520 : ! Local variables
521 : character(len=*), parameter :: sub = 'get_step_size'
522 : type(ESMF_TimeInterval) :: step_size ! timestep size
523 : integer :: rc
524 : !-----------------------------------------------------------------------------------------
525 :
526 19610162 : call ESMF_ClockGet(tm_clock, timeStep=step_size, rc=rc)
527 19610162 : call chkrc(rc, sub//': error return from ESMF_ClockGet')
528 19610162 : call ESMF_TimeIntervalGet(step_size, s=get_step_size, rc=rc)
529 19610162 : call chkrc(rc, sub//': error return from ESMF_ClockTimeIntervalGet')
530 :
531 392203240 : end function get_step_size
532 : !=========================================================================================
533 :
534 237646634 : integer function get_nstep()
535 :
536 : ! Return the timestep number.
537 :
538 : ! Local variables
539 : character(len=*), parameter :: sub = 'get_nstep'
540 : integer :: rc
541 : integer(ESMF_KIND_I8) :: step_no
542 : !-----------------------------------------------------------------------------------------
543 :
544 237646634 : call ESMF_ClockGet(tm_clock, advanceCount=step_no, rc=rc)
545 237646634 : call chkrc(rc, sub//': error return from ESMF_ClockGet')
546 237646634 : get_nstep = step_no
547 :
548 237646634 : end function get_nstep
549 : !=========================================================================================
550 :
551 27062940 : subroutine get_curr_date(yr, mon, day, tod, offset)
552 :
553 : ! Return date components valid at end of current timestep with an optional
554 : ! offset (positive or negative) in seconds.
555 :
556 : ! Arguments
557 : integer, intent(out) ::&
558 : yr, &! year
559 : mon, &! month
560 : day, &! day of month
561 : tod ! time of day (seconds past 0Z)
562 :
563 : integer, optional, intent(in) :: offset ! Offset from current time in seconds.
564 : ! Positive for future times, negative
565 : ! for previous times.
566 :
567 : ! Local variables
568 : character(len=*), parameter :: sub = 'get_curr_date'
569 : integer :: rc
570 : type(ESMF_Time) :: date
571 : type(ESMF_TimeInterval) :: off
572 : !-----------------------------------------------------------------------------------------
573 :
574 27062940 : call ESMF_ClockGet( tm_clock, currTime=date, rc=rc )
575 27062940 : call chkrc(rc, sub//': error return from ESMF_ClockGet')
576 :
577 27062940 : if (present(offset)) then
578 368640 : if (offset > 0) then
579 0 : call ESMF_TimeIntervalSet( off, s=offset, rc=rc )
580 0 : call chkrc(rc, sub//': error return from ESMF_TimeIntervalSet')
581 0 : date = date + off
582 368640 : else if (offset < 0) then
583 368640 : call ESMF_TimeIntervalSet( off, s=-offset, rc=rc )
584 368640 : call chkrc(rc, sub//': error return from ESMF_TimeIntervalSet')
585 368640 : date = date - off
586 : end if
587 : end if
588 :
589 27062940 : call ESMF_TimeGet(date, yy=yr, mm=mon, dd=day, s=tod, rc=rc)
590 27062940 : call chkrc(rc, sub//': error return from ESMF_TimeGet')
591 :
592 703636440 : end subroutine get_curr_date
593 : !=========================================================================================
594 :
595 0 : subroutine get_perp_date(yr, mon, day, tod, offset)
596 :
597 : ! Return time of day valid at end of current timestep and the components
598 : ! of the perpetual date (with an optional offset (positive or negative) in seconds.
599 :
600 : ! Arguments
601 : integer, intent(out) ::&
602 : yr, &! year
603 : mon, &! month
604 : day, &! day of month
605 : tod ! time of day (seconds past 0Z)
606 :
607 : integer, optional, intent(in) :: offset ! Offset from current time in seconds.
608 : ! Positive for future times, negative
609 : ! for previous times.
610 :
611 : ! Local variables
612 : character(len=*), parameter :: sub = 'get_perp_date'
613 : integer :: rc
614 : type(ESMF_Time) :: date
615 : type(ESMF_TimeInterval) :: DelTime
616 : !-----------------------------------------------------------------------------------------
617 :
618 0 : call ESMF_ClockGet( tm_clock, currTime=date, rc=rc )
619 : ! Get time of day add it to perpetual date
620 : ! Get year, month, day so that seconds are time-of-day rather than since start time
621 0 : call ESMF_TimeGet(date, yy=yr, mm=mon, dd=day, s=tod, rc=rc)
622 0 : call chkrc(rc, sub//': error return from ESMF_TimeGet')
623 0 : call ESMF_TimeIntervalSet(DelTime, s=tod, rc=rc)
624 0 : call chkrc(rc, sub//': error return from ESMF_TimeIntervalSet')
625 0 : date = tm_perp_date + DelTime
626 0 : if ( present(offset) )then
627 0 : call ESMF_TimeIntervalSet(DelTime, s=offset, rc=rc)
628 0 : call chkrc(rc, sub//': error return from ESMF_TimeIntervalSet')
629 0 : date = date + DelTime
630 : end if
631 : ! Get time of day from the result
632 : ! Get year, month, day so that seconds are time-of-day rather than since start time
633 0 : call ESMF_TimeGet(date, yy=yr, mm=mon, dd=day, s=tod, rc=rc)
634 :
635 : ! Get the date from the fixed perpetual date (in case it overflows to next day)
636 0 : call ESMF_TimeGet(tm_perp_date, yy=yr, mm=mon, dd=day, rc=rc)
637 0 : call chkrc(rc, sub//': error return from ESMF_TimeGet')
638 :
639 :
640 0 : end subroutine get_perp_date
641 : !=========================================================================================
642 :
643 0 : subroutine get_prev_date(yr, mon, day, tod)
644 :
645 : ! Return date components valid at beginning of current timestep.
646 :
647 : ! Arguments
648 : integer, intent(out) ::&
649 : yr, &! year
650 : mon, &! month
651 : day, &! day of month
652 : tod ! time of day (seconds past 0Z)
653 :
654 : ! Local variables
655 : character(len=*), parameter :: sub = 'get_prev_date'
656 : integer :: rc
657 : type(ESMF_Time) :: date
658 : !-----------------------------------------------------------------------------------------
659 :
660 0 : call ESMF_ClockGet(tm_clock, prevTime=date, rc=rc )
661 0 : call chkrc(rc, sub//': error return from ESMF_ClockGet')
662 :
663 0 : call ESMF_TimeGet(date, yy=yr, mm=mon, dd=day, s=tod, rc=rc)
664 0 : call chkrc(rc, sub//': error return from ESMF_TimeGet')
665 :
666 0 : end subroutine get_prev_date
667 : !=========================================================================================
668 :
669 0 : subroutine get_start_date(yr, mon, day, tod)
670 :
671 : ! Return date components valid at beginning of initial run.
672 :
673 : ! Arguments
674 : integer, intent(out) ::&
675 : yr, &! year
676 : mon, &! month
677 : day, &! day of month
678 : tod ! time of day (seconds past 0Z)
679 :
680 : ! Local variables
681 : character(len=*), parameter :: sub = 'get_start_date'
682 : integer :: rc
683 : type(ESMF_Time) :: date
684 : !-----------------------------------------------------------------------------------------
685 :
686 0 : call ESMF_ClockGet(tm_clock, startTime=date, rc=rc)
687 0 : call chkrc(rc, sub//': error return from ESMF_ClockGet')
688 :
689 0 : call ESMF_TimeGet(date, yy=yr, mm=mon, dd=day, s=tod, rc=rc)
690 0 : call chkrc(rc, sub//': error return from ESMF_TimeGet')
691 :
692 0 : end subroutine get_start_date
693 :
694 : !=========================================================================================
695 :
696 0 : subroutine get_stop_date(yr, mon, day, tod)
697 :
698 : ! Return date components valid at end of run
699 :
700 : ! Arguments
701 : integer, intent(out) ::&
702 : yr, &! year
703 : mon, &! month
704 : day, &! day of month
705 : tod ! time of day (seconds past 0Z)
706 :
707 : ! Local variables
708 : character(len=*), parameter :: sub = 'get_stop_date'
709 : integer :: rc
710 : type(ESMF_Time) :: date
711 : !----------------------------------------------------------------------------
712 :
713 0 : call ESMF_ClockGet(tm_clock, stopTime=date, rc=rc)
714 0 : call chkrc(rc, sub//': error return from ESMF_ClockGet')
715 :
716 0 : call ESMF_TimeGet(date, yy=yr, mm=mon, dd=day, s=tod, rc=rc)
717 0 : call chkrc(rc, sub//': error return from ESMF_TimeGet')
718 :
719 0 : end subroutine get_stop_date
720 :
721 : !=========================================================================================
722 :
723 0 : subroutine get_run_duration(nday, nsec)
724 :
725 : ! Return run duration in days and seconds
726 :
727 : ! Arguments
728 : integer, intent(out) ::&
729 : nday, &! number of days in interval
730 : nsec ! remainder in seconds
731 :
732 : ! Local variables
733 : character(len=*), parameter :: sub = 'get_run_duration'
734 : integer :: rc
735 : type(ESMF_Time) :: start_time, stop_time
736 : type(ESMF_TimeInterval) :: diff
737 : !----------------------------------------------------------------------------
738 :
739 0 : call ESMF_ClockGet(tm_clock, startTime=start_time, stopTime=stop_time, rc=rc)
740 0 : call chkrc(rc, sub//': error return from ESMF_ClockGet')
741 :
742 0 : diff = stop_time - start_time
743 :
744 0 : call ESMF_TimeIntervalGet(diff, d=nday, s=nsec, rc=rc)
745 0 : call chkrc(rc, sub//': error return from ESMF_TimeIntervalGet')
746 :
747 0 : end subroutine get_run_duration
748 :
749 : !=========================================================================================
750 :
751 122880 : subroutine get_ref_date(yr, mon, day, tod)
752 :
753 : ! Return date components of the reference date.
754 :
755 : ! Arguments
756 : integer, intent(out) ::&
757 : yr, &! year
758 : mon, &! month
759 : day, &! day of month
760 : tod ! time of day (seconds past 0Z)
761 :
762 : ! Local variables
763 : character(len=*), parameter :: sub = 'get_ref_date'
764 : integer :: rc
765 : type(ESMF_Time) :: date
766 : !-----------------------------------------------------------------------------------------
767 :
768 122880 : call ESMF_ClockGet(tm_clock, refTime=date, rc=rc)
769 122880 : call chkrc(rc, sub//': error return from ESMF_ClockGet')
770 :
771 122880 : call ESMF_TimeGet(date, yy=yr, mm=mon, dd=day, s=tod, rc=rc)
772 122880 : call chkrc(rc, sub//': error return from ESMF_TimeGet')
773 :
774 860160 : end subroutine get_ref_date
775 : !=========================================================================================
776 :
777 741120 : subroutine get_curr_time(days, seconds)
778 :
779 : ! Return time components valid at end of current timestep.
780 : ! Current time is the time interval between the current date and the reference date.
781 :
782 : ! Arguments
783 : integer, intent(out) ::&
784 : days, &! number of whole days in time interval
785 : seconds ! remaining seconds in time interval
786 :
787 : ! Local variables
788 : character(len=*), parameter :: sub = 'get_curr_time'
789 : integer :: rc
790 : type(ESMF_Time) :: cdate, rdate
791 : type(ESMF_TimeInterval) :: diff
792 : !-----------------------------------------------------------------------------------------
793 :
794 741120 : call ESMF_ClockGet( tm_clock, currTime=cdate, rc=rc )
795 741120 : call chkrc(rc, sub//': error return from ESMF_ClockGet')
796 :
797 741120 : call ESMF_ClockGet( tm_clock, refTime=rdate, rc=rc )
798 741120 : call chkrc(rc, sub//': error return from ESMF_ClockGet')
799 :
800 741120 : diff = cdate - rdate
801 :
802 741120 : call ESMF_TimeIntervalGet(diff, d=days, s=seconds, rc=rc)
803 741120 : call chkrc(rc, sub//': error return from ESMF_TimeIntervalGet')
804 :
805 23715840 : end subroutine get_curr_time
806 : !=========================================================================================
807 :
808 0 : subroutine get_prev_time(days, seconds)
809 :
810 : ! Return time components valid at beg of current timestep.
811 : ! prev time is the time interval between the prev date and the reference date.
812 :
813 : ! Arguments
814 : integer, intent(out) ::&
815 : days, &! number of whole days in time interval
816 : seconds ! remaining seconds in time interval
817 :
818 : ! Local variables
819 : character(len=*), parameter :: sub = 'get_prev_time'
820 : integer :: rc
821 : type(ESMF_Time) :: date, ref_date
822 : type(ESMF_TimeInterval) :: diff
823 : !-----------------------------------------------------------------------------------------
824 :
825 0 : call ESMF_ClockGet(tm_clock, prevTime=date, rc=rc )
826 0 : call chkrc(rc, sub//': error return from ESMF_ClockGet for prevTime')
827 0 : call ESMF_ClockGet(tm_clock, refTime=ref_date, rc=rc )
828 0 : call chkrc(rc, sub//': error return from ESMF_ClockGet for refTime')
829 0 : diff = date - ref_date
830 0 : call ESMF_TimeIntervalGet( diff, d=days, s=seconds, rc=rc )
831 0 : call chkrc(rc, sub//': error return from ESMF_TimeintervalGet')
832 :
833 0 : end subroutine get_prev_time
834 : !=========================================================================================
835 :
836 32401752 : function get_curr_calday(offset)
837 :
838 : ! Return calendar day at end of current timestep with optional offset.
839 : ! Calendar day 1.0 = 0Z on Jan 1.
840 :
841 : ! Arguments
842 : integer, optional, intent(in) :: offset ! Offset from current time in seconds.
843 : ! Positive for future times, negative
844 : ! for previous times.
845 : ! Return value
846 : real(r8) :: get_curr_calday
847 :
848 : ! Local variables
849 : character(len=*), parameter :: sub = 'get_curr_calday'
850 : integer :: rc
851 : type(ESMF_Time) :: date
852 : type(ESMF_TimeInterval) :: off, diurnal
853 : integer :: year, month, day, tod
854 : !-----------------------------------------------------------------------------------------
855 :
856 32401752 : call ESMF_ClockGet( tm_clock, currTime=date, rc=rc )
857 32401752 : call chkrc(rc, sub//': error return from ESMF_ClockGet')
858 :
859 32401752 : if (present(offset)) then
860 2978352 : if (offset > 0) then
861 2978352 : call ESMF_TimeIntervalSet( off, s=offset, rc=rc )
862 2978352 : call chkrc(rc, sub//': error return from ESMF_TimeIntervalSet')
863 2978352 : date = date + off
864 0 : else if (offset < 0) then
865 0 : call ESMF_TimeIntervalSet( off, s=-offset, rc=rc )
866 0 : call chkrc(rc, sub//': error return from ESMF_TimeIntervalSet')
867 0 : date = date - off
868 : end if
869 : end if
870 :
871 32401752 : if ( tm_perp_calendar ) then
872 : ! Get current time-of-day from clock
873 0 : call ESMF_TimeGet(date, yy=year, mm=month, dd=day, s=tod, rc=rc)
874 0 : call chkrc(rc, sub//': error return from ESMF_TimeGet')
875 : ! Get date from perpetual date add time-of-day to it
876 0 : call ESMF_TimeIntervalSet( diurnal, s=tod, rc=rc )
877 0 : call chkrc(rc, sub//': error return from ESMF_TimeIntervalSet')
878 0 : date = tm_perp_date + diurnal
879 : !!!! write(iulog,*) ' tod = ', tod
880 : !!!! call ESMF_TimePrint( date, "string" )
881 : end if
882 :
883 32401752 : call ESMF_TimeGet( date, dayOfYear_r8=get_curr_calday, rc=rc )
884 32401752 : call chkrc(rc, sub//': error return from ESMF_TimeGet')
885 :
886 : !
887 : ! WARNING: Gregorian calendar fakes day 366
888 : !
889 : ! The zenith angle calculation is only capable of using a 365-day calendar.
890 : ! If a Gregorian calendar is being used, the last day of a leap year (day 366)
891 : ! is sent to the model as a repetition of the previous day (day 365).
892 : ! This is done by decrementing calday by 1 immediately below.
893 : ! bundy, July 2008
894 : !
895 : if (( get_curr_calday > 366.0_r8 ) .and. ( get_curr_calday <= 367.0_r8 ) &
896 32401752 : .and. (timemgr_is_caltype(trim(shr_cal_gregorian)))) then
897 0 : get_curr_calday = get_curr_calday - 1.0_r8
898 : endif
899 :
900 32401752 : if ( (get_curr_calday < 1.0_r8) .or. (get_curr_calday > 366.0_r8) )then
901 0 : write(iulog,*) 'atm '//sub//' calday = ', get_curr_calday
902 0 : if ( present(offset) ) write(iulog,*) 'offset = ', offset
903 0 : call endrun( sub//': error get_curr_calday out of bounds' )
904 : end if
905 :
906 1458078840 : end function get_curr_calday
907 :
908 : !==========================================================================
909 : ! return julian day
910 0 : function get_julday(yr_in,mon,day,sec) result(julday)
911 :
912 : integer, intent(in) :: yr_in,mon,day,sec
913 :
914 : real(r8) :: julday
915 :
916 : integer :: yr
917 : integer :: itimes(3), j, a,y,m
918 :
919 0 : yr = yr_in
920 :
921 0 : if (yr < 1000) then
922 0 : if (yr < 40) then
923 0 : yr = yr + 2000
924 : else
925 0 : yr = yr + 1900
926 : endif
927 : endif
928 :
929 0 : itimes(1) = int(mon)
930 0 : itimes(2) = int(day)
931 0 : itimes(3) = int(yr)
932 :
933 0 : a = int((14._r8-real(itimes(1),kind=r8))/12._r8)
934 0 : y = itimes(3)+4800-a
935 0 : m = itimes(1)+12*a-3
936 : j = itimes(2) + int((153._r8*real(m,kind=r8)+2._r8) / 5._r8) + 365*y + &
937 0 : int(real(y,kind=r8)/4._r8) - int(real(y,kind=r8)/100._r8) + int(real(y,kind=r8)/400._r8)- 32045
938 0 : julday = real(j,kind=r8) + real(sec,kind=r8)/86400._r8
939 :
940 0 : end function get_julday
941 : !==========================================================================
942 : !=========================================================================================
943 :
944 36864 : function get_calday(ymd, tod)
945 :
946 : ! Return calendar day corresponding to specified time instant.
947 : ! Calendar day 1.0 = 0Z on Jan 1.
948 :
949 : ! Arguments
950 : integer, intent(in) :: &
951 : ymd, &! date in yearmmdd format
952 : tod ! time of day (seconds past 0Z)
953 :
954 : ! Return value
955 : real(r8) :: get_calday
956 :
957 : ! Local variables
958 : character(len=*), parameter :: sub = 'get_calday'
959 : integer :: rc ! return code
960 : type(ESMF_Time) :: date
961 : !-----------------------------------------------------------------------------------------
962 :
963 36864 : date = TimeSetymd( ymd, tod, "get_calday" )
964 36864 : call ESMF_TimeGet( date, dayOfYear_r8=get_calday, rc=rc )
965 36864 : call chkrc(rc, sub//': error return from ESMF_TimeGet')
966 :
967 : !
968 : ! WARNING: Gregorian calendar fakes day 366
969 : !
970 : ! The zenith angle calculation is only capable of using a 365-day calendar.
971 : ! If a Gregorian calendar is being used, the last day of a leap year (day 366)
972 : ! is sent to the model as a repetition of the previous day (day 365).
973 : ! This is done by decrementing calday by 1 immediately below.
974 : ! bundy, July 2008
975 : !
976 : if (( get_calday > 366.0_r8 ) .and. ( get_calday <= 367.0_r8 ) &
977 36864 : .and. (timemgr_is_caltype(trim(shr_cal_gregorian)))) then
978 0 : get_calday = get_calday - 1.0_r8
979 : endif
980 :
981 36864 : if ( (get_calday < 1.0_r8) .or. (get_calday > 366.0_r8) )then
982 0 : write(iulog,*) 'atm '//sub//' calday = ', get_calday
983 0 : call endrun( sub//': error calday out of range' )
984 : end if
985 :
986 258048 : end function get_calday
987 : !=========================================================================================
988 :
989 122880 : character(len=SHR_KIND_CS) function timemgr_get_calendar_cf()
990 :
991 : ! Return cf standard for calendar type
992 :
993 : ! Local variables
994 : character(len=*), parameter :: sub = 'timemgr_get_calendar_cf'
995 : character(len=len(calendar)) :: caltmp
996 : !-----------------------------------------------------------------------------------------
997 :
998 122880 : caltmp = to_upper(trim(calendar) )
999 122880 : if ( trim(caltmp) == trim(shr_cal_noleap) ) then
1000 122880 : timemgr_get_calendar_cf = 'noleap'
1001 0 : else if ( trim(caltmp) == trim(shr_cal_gregorian) ) then
1002 0 : timemgr_get_calendar_cf = 'gregorian'
1003 : else
1004 0 : write(iulog,*)sub,': unrecognized calendar specified: ',calendar
1005 0 : call endrun
1006 : end if
1007 :
1008 122880 : end function timemgr_get_calendar_cf
1009 : !=========================================================================================
1010 :
1011 32438616 : function timemgr_is_caltype( cal_in )
1012 :
1013 : ! Return true if incoming calendar type string matches actual calendar type in use
1014 :
1015 : character(len=*), intent(in) :: cal_in
1016 :
1017 : ! Return value
1018 : logical :: timemgr_is_caltype
1019 :
1020 : !-----------------------------------------------------------------------------------------
1021 :
1022 32438616 : timemgr_is_caltype = ( to_upper(trim(calendar)) == to_upper(trim(cal_in)) )
1023 :
1024 32438616 : end function timemgr_is_caltype
1025 : !=========================================================================================
1026 :
1027 1861656 : function is_end_curr_day()
1028 :
1029 : ! Return true if current timestep is last timestep in current day.
1030 :
1031 : ! Return value
1032 : logical :: is_end_curr_day
1033 :
1034 : ! Local variables
1035 : integer ::&
1036 : yr, &! year
1037 : mon, &! month
1038 : day, &! day of month
1039 : tod ! time of day (seconds past 0Z)
1040 : !-----------------------------------------------------------------------------------------
1041 :
1042 1861656 : call get_curr_date(yr, mon, day, tod)
1043 1861656 : is_end_curr_day = (tod == 0)
1044 :
1045 1861656 : end function is_end_curr_day
1046 : !=========================================================================================
1047 :
1048 0 : logical function is_end_curr_month()
1049 :
1050 : ! Return true if current timestep is last timestep in current month.
1051 :
1052 : ! Local variables
1053 : integer ::&
1054 : yr, &! year
1055 : mon, &! month
1056 : day, &! day of month
1057 : tod ! time of day (seconds past 0Z)
1058 : !-----------------------------------------------------------------------------------------
1059 :
1060 0 : call get_curr_date(yr, mon, day, tod)
1061 0 : is_end_curr_month = (day == 1 .and. tod == 0)
1062 :
1063 0 : end function is_end_curr_month
1064 : !=========================================================================================
1065 :
1066 10465872 : logical function is_first_step()
1067 :
1068 : ! Return true on first step of initial run only.
1069 :
1070 : ! Local variables
1071 : character(len=*), parameter :: sub = 'is_first_step'
1072 : integer :: rc
1073 : integer :: nstep
1074 : integer(ESMF_KIND_I8) :: step_no
1075 : !-----------------------------------------------------------------------------------------
1076 :
1077 10465872 : call ESMF_ClockGet( tm_clock, advanceCount=step_no, rc=rc )
1078 10465872 : call chkrc(rc, sub//': error return from ESMF_ClockGet')
1079 10465872 : nstep = step_no
1080 10465872 : is_first_step = (nstep == 0)
1081 :
1082 10465872 : end function is_first_step
1083 : !=========================================================================================
1084 :
1085 6004368936 : logical function is_first_restart_step()
1086 :
1087 : ! Return true on first step of restart run only.
1088 :
1089 : !-----------------------------------------------------------------------------------------
1090 :
1091 6004368936 : is_first_restart_step = tm_first_restart_step
1092 :
1093 6004368936 : end function is_first_restart_step
1094 : !=========================================================================================
1095 :
1096 369408 : logical function is_last_step()
1097 :
1098 : ! Return true on last timestep.
1099 :
1100 : ! Local variables
1101 : character(len=*), parameter :: sub = 'is_last_step'
1102 : type(ESMF_Time) :: stop_date
1103 : type(ESMF_Time) :: curr_date
1104 : type(ESMF_TimeInterval) :: time_step
1105 : integer :: rc
1106 : !-----------------------------------------------------------------------------------------
1107 :
1108 : call ESMF_ClockGet( tm_clock, stopTime=stop_date, &
1109 369408 : currTime=curr_date, TimeStep=time_step, rc=rc )
1110 369408 : call chkrc(rc, sub//': error return from ESMF_ClockGet')
1111 369408 : if ( curr_date+time_step > stop_date ) then
1112 : is_last_step = .true.
1113 : else
1114 367872 : is_last_step = .false.
1115 : end if
1116 :
1117 11821056 : end function is_last_step
1118 : !=========================================================================================
1119 :
1120 0 : logical function is_perpetual()
1121 :
1122 : ! Return true on last timestep.
1123 :
1124 : !-----------------------------------------------------------------------------------------
1125 :
1126 0 : is_perpetual = tm_perp_calendar
1127 :
1128 0 : end function is_perpetual
1129 :
1130 : !=========================================================================================
1131 :
1132 8988000 : subroutine timemgr_datediff(ymd1, tod1, ymd2, tod2, days)
1133 :
1134 : ! Calculate the difference (ymd2,tod2) - (ymd1,tod1) and return the result in days.
1135 :
1136 : ! Arguments
1137 : integer, intent(in) ::&
1138 : ymd1, &! date1 in yyyymmdd format
1139 : tod1, &! time of day relative to date1 (seconds past 0Z)
1140 : ymd2, &! date2 in yyyymmdd format
1141 : tod2 ! time of day relative to date2 (seconds past 0Z)
1142 :
1143 : real(r8) :: days ! (ymd2,tod2)-(ymd1,tod1) in days
1144 :
1145 : ! Local variables
1146 : character(len=*), parameter :: sub = 'timemgr_datediff'
1147 : integer :: rc ! return code
1148 :
1149 : type(ESMF_Time) :: date1
1150 : type(ESMF_Time) :: date2
1151 : type(ESMF_TimeInterval) :: diff
1152 : !-----------------------------------------------------------------------------------------
1153 :
1154 8988000 : date1 = TimeSetymd( ymd1, tod1, "date1" )
1155 8988000 : date2 = TimeSetymd( ymd2, tod2, "date2" )
1156 8988000 : diff = date2 - date1
1157 8988000 : call ESMF_TimeIntervalGet( diff, d_r8=days, rc=rc )
1158 8988000 : call chkrc(rc, sub//': error return from ESMF_TimeIntervalGet')
1159 :
1160 287616000 : end subroutine timemgr_datediff
1161 :
1162 : !=========================================================================================
1163 :
1164 0 : subroutine timemgr_time_ge(ymd1, tod1, ymd2, tod2, time2_ge_time1)
1165 :
1166 : ! time2_ge_time1 is set to true if (ymd2,tod2) is later than or equal to (ymd1,tod1)
1167 :
1168 : ! Arguments
1169 : integer, intent(in) ::&
1170 : ymd1, &! date1 in yyyymmdd format
1171 : tod1, &! time of day relative to date1 (seconds past 0Z)
1172 : ymd2, &! date2 in yyyymmdd format
1173 : tod2 ! time of day relative to date2 (seconds past 0Z)
1174 :
1175 : logical :: time2_ge_time1
1176 :
1177 : ! Local variables
1178 : character(len=*), parameter :: sub = 'timemgr_time_ge'
1179 : integer :: rc ! return code
1180 :
1181 : type(ESMF_Time) :: time1, time2
1182 : !-----------------------------------------------------------------------------------------
1183 :
1184 0 : time1 = TimeSetymd( ymd1, tod1, "date1" )
1185 0 : time2 = TimeSetymd( ymd2, tod2, "date2" )
1186 0 : time2_ge_time1 = (time2 >= time1)
1187 :
1188 0 : end subroutine timemgr_time_ge
1189 :
1190 : !=========================================================================================
1191 :
1192 0 : subroutine timemgr_time_inc(ymd1, tod1, ymd2, tod2, inc_s, inc_h, inc_d)
1193 :
1194 : ! Increment the time instant (ymd1,tod1) by an interval and return the resulting
1195 : ! time instant (ymd2,tod2).
1196 :
1197 : ! Arguments
1198 : integer, intent(in) ::&
1199 : ymd1, &! date1 in yyyymmdd format
1200 : tod1 ! time of day relative to date1 (seconds past 0Z)
1201 :
1202 : integer, intent(out) ::&
1203 : ymd2, &! date2 in yyyymmdd format
1204 : tod2 ! time of day relative to date2 (seconds past 0Z)
1205 :
1206 : integer, intent(in), optional ::&
1207 : inc_s, &! number of seconds in interval
1208 : inc_h, &! number of hours in interval
1209 : inc_d ! number of days in interval
1210 :
1211 : ! Local variables
1212 : character(len=*), parameter :: sub = 'timemgr_time_inc'
1213 : integer :: rc ! return code
1214 :
1215 : type(ESMF_Time) :: date1
1216 : type(ESMF_Time) :: date2
1217 : type(ESMF_TimeInterval) :: t_interval
1218 : integer :: year, month, day
1219 : !-----------------------------------------------------------------------------------------
1220 :
1221 : ! set esmf time object
1222 0 : date1 = TimeSetymd( ymd1, tod1, "date1" )
1223 :
1224 : ! set esmf time interval object
1225 0 : if (present(inc_s)) then
1226 0 : call ESMF_TimeIntervalSet(t_interval, s=inc_s, rc=rc)
1227 0 : else if (present(inc_h)) then
1228 0 : call ESMF_TimeIntervalSet(t_interval, h=inc_h, rc=rc)
1229 0 : else if (present(inc_d)) then
1230 0 : call ESMF_TimeIntervalSet(t_interval, d=inc_d, rc=rc)
1231 : else
1232 0 : call endrun(sub//': one of the args inc_s, inc_h, or inc_d must be set')
1233 : end if
1234 0 : call chkrc(rc, sub//': error return from ESMF_TimeIntervalSet')
1235 :
1236 : ! increment the time instant
1237 0 : date2 = date1 + t_interval
1238 :
1239 : ! extract the time components
1240 0 : call ESMF_TimeGet(date2, yy=year, mm=month, dd=day, s=tod2, rc=rc)
1241 0 : call chkrc(rc, sub//': error return from ESMF_TimeGet')
1242 0 : ymd2 = year*10000 + month*100 + day
1243 :
1244 0 : end subroutine timemgr_time_inc
1245 :
1246 : !=========================================================================================
1247 :
1248 1413791778 : subroutine chkrc(rc, mes)
1249 : integer, intent(in) :: rc ! return code from time management library
1250 : character(len=*), intent(in) :: mes ! error message
1251 1413791778 : if ( rc == ESMF_SUCCESS ) return
1252 0 : write(iulog,*) mes
1253 0 : call endrun ('CHKRC')
1254 : end subroutine chkrc
1255 :
1256 : end module time_manager
|