MOM6
mom_cap_time Module Reference

Detailed Description

This was originally share code in CIME, but required CIME as a dependency to build the MOM cap. The options here for setting a restart alarm are useful for all caps, so a second step is to determine if/how these could be offered more generally in a shared library. For now we really want the MOM cap to only depend on MOM and ESMF/NUOPC.

Functions/Subroutines

subroutine, public alarminit (clock, alarm, option, opt_n, opt_ymd, opt_tod, RefTime, alarmname, rc)
 Setup an alarm in a clock. The ringtime sent to AlarmCreate MUST be the next alarm time. If you send an arbitrary but proper ringtime from the past and the ring interval, the alarm will always go off on the next clock advance and this will cause serious problems. Even if it makes sense to initialize an alarm with some reference time and the alarm interval, that reference time has to be advance forward to be >= the current time. In the logic below we set an appropriate "NextAlarm" and then we make sure to advance it properly based on the ring interval. More...
 
subroutine, private timeinit (Time, ymd, cal, tod, desc, logunit, rc)
 Creates the ESMF_Time object corresponding to the given input time, given in YMD (Year Month Day) and TOD (Time-of-day) format. Sets the time by an integer as YYYYMMDD and integer seconds in the day. More...
 
subroutine, private date2ymd (date, year, month, day)
 Converts a coded-date (yyyymmdd) into calendar year,month,day. More...
 

Variables

character(len= *), parameter, private optnone = "none"
 
character(len= *), parameter, private optnever = "never"
 
character(len= *), parameter, private optnsteps = "nsteps"
 
character(len= *), parameter, private optnstep = "nstep"
 
character(len= *), parameter, private optnseconds = "nseconds"
 
character(len= *), parameter, private optnsecond = "nsecond"
 
character(len= *), parameter, private optnminutes = "nminutes"
 
character(len= *), parameter, private optnminute = "nminute"
 
character(len= *), parameter, private optnhours = "nhours"
 
character(len= *), parameter, private optnhour = "nhour"
 
character(len= *), parameter, private optndays = "ndays"
 
character(len= *), parameter, private optnday = "nday"
 
character(len= *), parameter, private optnmonths = "nmonths"
 
character(len= *), parameter, private optnmonth = "nmonth"
 
character(len= *), parameter, private optnyears = "nyears"
 
character(len= *), parameter, private optnyear = "nyear"
 
character(len= *), parameter, private optmonthly = "monthly"
 
character(len= *), parameter, private optyearly = "yearly"
 
character(len= *), parameter, private optdate = "date"
 
character(len= *), parameter, private optifdays0 = "ifdays0"
 
character(len= *), parameter, private optglccouplingperiod = "glc_coupling_period"
 
integer, parameter secperday = 86400
 
character(len= *), parameter u_file_u = __FILE__
 

Function/Subroutine Documentation

◆ alarminit()

subroutine, public mom_cap_time::alarminit ( type(esmf_clock), intent(inout)  clock,
type(esmf_alarm), intent(inout)  alarm,
character(len=*), intent(in)  option,
integer, intent(in), optional  opt_n,
integer, intent(in), optional  opt_ymd,
integer, intent(in), optional  opt_tod,
type(esmf_time), intent(in), optional  RefTime,
character(len=*), intent(in), optional  alarmname,
integer, intent(inout)  rc 
)

Setup an alarm in a clock. The ringtime sent to AlarmCreate MUST be the next alarm time. If you send an arbitrary but proper ringtime from the past and the ring interval, the alarm will always go off on the next clock advance and this will cause serious problems. Even if it makes sense to initialize an alarm with some reference time and the alarm interval, that reference time has to be advance forward to be >= the current time. In the logic below we set an appropriate "NextAlarm" and then we make sure to advance it properly based on the ring interval.

Parameters
[in,out]clockESMF clock
[in,out]alarmESMF alarm
[in]optionalarm option
[in]opt_nalarm freq
[in]opt_ymdalarm ymd
[in]opt_todalarm tod (sec)
[in]reftimeref time
[in]alarmnamealarm name
[in,out]rcReturn code

Definition at line 69 of file mom_cap_time.F90.

69  type(ESMF_Clock) , intent(inout) :: clock !< ESMF clock
70  type(ESMF_Alarm) , intent(inout) :: alarm !< ESMF alarm
71  character(len=*) , intent(in) :: option !< alarm option
72  integer , optional , intent(in) :: opt_n !< alarm freq
73  integer , optional , intent(in) :: opt_ymd !< alarm ymd
74  integer , optional , intent(in) :: opt_tod !< alarm tod (sec)
75  type(ESMF_Time) , optional , intent(in) :: RefTime !< ref time
76  character(len=*) , optional , intent(in) :: alarmname !< alarm name
77  integer , intent(inout) :: rc !< Return code
78 
79  ! local variables
80  type(ESMF_Calendar) :: cal ! calendar
81  integer :: lymd ! local ymd
82  integer :: ltod ! local tod
83  integer :: cyy,cmm,cdd,csec ! time info
84  integer :: nyy,nmm,ndd,nsec ! time info
85  character(len=64) :: lalarmname ! local alarm name
86  logical :: update_nextalarm ! update next alarm
87  type(ESMF_Time) :: CurrTime ! Current Time
88  type(ESMF_Time) :: NextAlarm ! Next restart alarm time
89  type(ESMF_TimeInterval) :: AlarmInterval ! Alarm interval
90  character(len=*), parameter :: subname = '(AlarmInit): '
91  !-------------------------------------------------------------------------------
92 
93  rc = esmf_success
94 
95  lalarmname = 'alarm_unknown'
96  if (present(alarmname)) lalarmname = trim(alarmname)
97  ltod = 0
98  if (present(opt_tod)) ltod = opt_tod
99  lymd = -1
100  if (present(opt_ymd)) lymd = opt_ymd
101 
102  ! verify parameters
103  if (trim(option) == optnsteps .or. trim(option) == optnstep .or. &
104  trim(option) == optnseconds .or. trim(option) == optnsecond .or. &
105  trim(option) == optnminutes .or. trim(option) == optnminute .or. &
106  trim(option) == optnhours .or. trim(option) == optnhour .or. &
107  trim(option) == optndays .or. trim(option) == optnday .or. &
108  trim(option) == optnmonths .or. trim(option) == optnmonth .or. &
109  trim(option) == optnyears .or. trim(option) == optnyear .or. &
110  trim(option) == optifdays0) then
111  if (.not. present(opt_n)) then
112  call esmf_logseterror(esmf_rc_arg_bad, &
113  msg=subname//trim(option)//' requires opt_n', &
114  line=__line__, &
115  file=__file__, rctoreturn=rc)
116  return
117  endif
118  if (opt_n <= 0) then
119  call esmf_logseterror(esmf_rc_arg_bad, &
120  msg=subname//trim(option)//' invalid opt_n', &
121  line=__line__, &
122  file=__file__, rctoreturn=rc)
123  return
124  endif
125  endif
126 
127  call esmf_clockget(clock, currtime=currtime, rc=rc)
128  if (esmf_logfounderror(rctocheck=rc, msg=esmf_logerr_passthru, &
129  line=__line__, &
130  file=__file__)) &
131  return
132 
133  call esmf_timeget(currtime, yy=cyy, mm=cmm, dd=cdd, s=csec, rc=rc )
134  if (esmf_logfounderror(rctocheck=rc, msg=esmf_logerr_passthru, &
135  line=__line__, &
136  file=__file__)) &
137  return
138 
139  call esmf_timeget(currtime, yy=nyy, mm=nmm, dd=ndd, s=nsec, rc=rc )
140  if (esmf_logfounderror(rctocheck=rc, msg=esmf_logerr_passthru, &
141  line=__line__, &
142  file=__file__)) &
143  return
144 
145  ! initial guess of next alarm, this will be updated below
146  if (present(reftime)) then
147  nextalarm = reftime
148  else
149  nextalarm = currtime
150  endif
151 
152  ! Determine calendar
153  call esmf_clockget(clock, calendar=cal, rc=rc)
154  if (esmf_logfounderror(rctocheck=rc, msg=esmf_logerr_passthru, &
155  line=__line__, &
156  file=__file__)) &
157  return
158 
159  ! Determine inputs for call to create alarm
160  selectcase (trim(option))
161 
162  case (optnone, optnever)
163  call esmf_timeintervalset(alarminterval, yy=9999, rc=rc)
164  if (esmf_logfounderror(rctocheck=rc, msg=esmf_logerr_passthru, &
165  line=__line__, &
166  file=__file__)) &
167  return
168  call esmf_timeset( nextalarm, yy=9999, mm=12, dd=1, s=0, calendar=cal, rc=rc )
169  if (esmf_logfounderror(rctocheck=rc, msg=esmf_logerr_passthru, &
170  line=__line__, &
171  file=__file__)) &
172  return
173  update_nextalarm = .false.
174 
175  case (optdate)
176  if (.not. present(opt_ymd)) then
177  call esmf_logseterror(esmf_rc_arg_bad, &
178  msg=subname//trim(option)//' requires opt_ymd', &
179  line=__line__, &
180  file=__file__, rctoreturn=rc)
181  return
182  endif
183  if (lymd < 0 .or. ltod < 0) then
184  call esmf_logseterror(esmf_rc_arg_bad, &
185  msg=subname//trim(option)//'opt_ymd, opt_tod invalid', &
186  line=__line__, &
187  file=__file__, rctoreturn=rc)
188  return
189  endif
190  call esmf_timeintervalset(alarminterval, yy=9999, rc=rc)
191  if (esmf_logfounderror(rctocheck=rc, msg=esmf_logerr_passthru, &
192  line=__line__, &
193  file=__file__)) &
194  return
195  call timeinit(nextalarm, lymd, cal, tod=ltod, desc="optDate", rc=rc)
196  if (esmf_logfounderror(rctocheck=rc, msg=esmf_logerr_passthru, &
197  line=__line__, &
198  file=__file__)) &
199  return
200  update_nextalarm = .false.
201 
202  case (optifdays0)
203  if (.not. present(opt_ymd)) then
204  call esmf_logseterror(esmf_rc_arg_bad, &
205  msg=subname//trim(option)//' requires opt_ymd', &
206  line=__line__, &
207  file=__file__, rctoreturn=rc)
208  return
209  endif
210  call esmf_timeintervalset(alarminterval, mm=1, rc=rc)
211  if (esmf_logfounderror(rctocheck=rc, msg=esmf_logerr_passthru, &
212  line=__line__, &
213  file=__file__)) &
214  return
215  call esmf_timeset( nextalarm, yy=cyy, mm=cmm, dd=opt_n, s=0, calendar=cal, rc=rc )
216  if (esmf_logfounderror(rctocheck=rc, msg=esmf_logerr_passthru, &
217  line=__line__, &
218  file=__file__)) &
219  return
220  update_nextalarm = .true.
221 
222  case (optnsteps, optnstep)
223  call esmf_clockget(clock, timestep=alarminterval, rc=rc)
224  if (esmf_logfounderror(rctocheck=rc, msg=esmf_logerr_passthru, &
225  line=__line__, &
226  file=__file__)) &
227  return
228  alarminterval = alarminterval * opt_n
229  update_nextalarm = .true.
230 
231  case (optnseconds, optnsecond)
232  call esmf_timeintervalset(alarminterval, s=1, rc=rc)
233  if (esmf_logfounderror(rctocheck=rc, msg=esmf_logerr_passthru, &
234  line=__line__, &
235  file=__file__)) &
236  return
237  alarminterval = alarminterval * opt_n
238  update_nextalarm = .true.
239 
240  case (optnminutes, optnminute)
241  call esmf_timeintervalset(alarminterval, s=60, rc=rc)
242  if (esmf_logfounderror(rctocheck=rc, msg=esmf_logerr_passthru, &
243  line=__line__, &
244  file=__file__)) &
245  return
246  alarminterval = alarminterval * opt_n
247  update_nextalarm = .true.
248 
249  case (optnhours, optnhour)
250  call esmf_timeintervalset(alarminterval, s=3600, rc=rc)
251  if (esmf_logfounderror(rctocheck=rc, msg=esmf_logerr_passthru, &
252  line=__line__, &
253  file=__file__)) &
254  return
255  alarminterval = alarminterval * opt_n
256  update_nextalarm = .true.
257 
258  case (optndays, optnday)
259  call esmf_timeintervalset(alarminterval, d=1, rc=rc)
260  if (esmf_logfounderror(rctocheck=rc, msg=esmf_logerr_passthru, &
261  line=__line__, &
262  file=__file__)) &
263  return
264  alarminterval = alarminterval * opt_n
265  update_nextalarm = .true.
266 
267  case (optnmonths, optnmonth)
268  call esmf_timeintervalset(alarminterval, mm=1, rc=rc)
269  if (esmf_logfounderror(rctocheck=rc, msg=esmf_logerr_passthru, &
270  line=__line__, &
271  file=__file__)) &
272  return
273  alarminterval = alarminterval * opt_n
274  update_nextalarm = .true.
275 
276  case (optmonthly)
277  call esmf_timeintervalset(alarminterval, mm=1, rc=rc)
278  if (esmf_logfounderror(rctocheck=rc, msg=esmf_logerr_passthru, &
279  line=__line__, &
280  file=__file__)) &
281  return
282  call esmf_timeset( nextalarm, yy=cyy, mm=cmm, dd=1, s=0, calendar=cal, rc=rc )
283  if (esmf_logfounderror(rctocheck=rc, msg=esmf_logerr_passthru, &
284  line=__line__, &
285  file=__file__)) &
286  return
287  update_nextalarm = .true.
288 
289  case (optnyears, optnyear)
290  call esmf_timeintervalset(alarminterval, yy=1, rc=rc)
291  if (esmf_logfounderror(rctocheck=rc, msg=esmf_logerr_passthru, &
292  line=__line__, &
293  file=__file__)) &
294  return
295  alarminterval = alarminterval * opt_n
296  update_nextalarm = .true.
297 
298  case (optyearly)
299  call esmf_timeintervalset(alarminterval, yy=1, rc=rc)
300  if (esmf_logfounderror(rctocheck=rc, msg=esmf_logerr_passthru, &
301  line=__line__, &
302  file=__file__)) &
303  return
304  call esmf_timeset( nextalarm, yy=cyy, mm=1, dd=1, s=0, calendar=cal, rc=rc )
305  if (esmf_logfounderror(rctocheck=rc, msg=esmf_logerr_passthru, &
306  line=__line__, &
307  file=__file__)) &
308  return
309  update_nextalarm = .true.
310 
311  case default
312  call esmf_logseterror(esmf_rc_arg_bad, &
313  msg=subname//' unknown option: '//trim(option), &
314  line=__line__, &
315  file=__file__, rctoreturn=rc)
316  return
317 
318  end select
319 
320  ! --------------------------------------------------------------------------------
321  ! --- AlarmInterval and NextAlarm should be set ---
322  ! --------------------------------------------------------------------------------
323 
324  ! --- advance Next Alarm so it won't ring on first timestep for
325  ! --- most options above. go back one alarminterval just to be careful
326 
327  if (update_nextalarm) then
328  nextalarm = nextalarm - alarminterval
329  do while (nextalarm <= currtime)
330  nextalarm = nextalarm + alarminterval
331  enddo
332  endif
333 
334  alarm = esmf_alarmcreate( name=lalarmname, clock=clock, ringtime=nextalarm, ringinterval=alarminterval, rc=rc)
335  if (esmf_logfounderror(rctocheck=rc, msg=esmf_logerr_passthru, &
336  line=__line__, &
337  file=__file__)) &
338  return
339 

References optdate, optifdays0, optmonthly, optnday, optndays, optnever, optnhour, optnhours, optnminute, optnminutes, optnmonth, optnmonths, optnone, optnsecond, optnseconds, optnstep, optnsteps, optnyear, optnyears, optyearly, and timeinit().

Referenced by mom_cap_mod::modelsetrunclock().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ date2ymd()

subroutine, private mom_cap_time::date2ymd ( integer, intent(in)  date,
integer, intent(out)  year,
integer, intent(out)  month,
integer, intent(out)  day 
)
private

Converts a coded-date (yyyymmdd) into calendar year,month,day.

Parameters
[in]datecoded-date (yyyymmdd)
[out]daycalendar year,month,day

Definition at line 390 of file mom_cap_time.F90.

390  integer, intent(in) :: date !< coded-date (yyyymmdd)
391  integer, intent(out) :: year,month,day !< calendar year,month,day
392 
393  ! local variables
394  integer :: tdate ! temporary date
395  character(*),parameter :: subName = "(date2ymd)"
396  !-------------------------------------------------------------------------------
397 
398  tdate = abs(date)
399  year = int(tdate/10000)
400  if (date < 0) then
401  year = -year
402  endif
403  month = int( mod(tdate,10000)/ 100)
404  day = mod(tdate, 100)
405 

Referenced by timeinit().

Here is the caller graph for this function:

◆ timeinit()

subroutine, private mom_cap_time::timeinit ( type(esmf_time), intent(inout)  Time,
integer, intent(in)  ymd,
type(esmf_calendar), intent(in)  cal,
integer, intent(in), optional  tod,
character(len=*), intent(in), optional  desc,
integer, intent(in), optional  logunit,
integer, intent(out), optional  rc 
)
private

Creates the ESMF_Time object corresponding to the given input time, given in YMD (Year Month Day) and TOD (Time-of-day) format. Sets the time by an integer as YYYYMMDD and integer seconds in the day.

Parameters
[in,out]timeESMF time
[in]ymdyear, month, day YYYYMMDD
[in]calESMF calendar
[in]todtime of day in [sec]
[in]descdescription of time to set
[in]logunitUnit for stdout output
[out]rcReturn code

Definition at line 346 of file mom_cap_time.F90.

346  type(ESMF_Time) , intent(inout) :: Time !< ESMF time
347  integer , intent(in) :: ymd !< year, month, day YYYYMMDD
348  type(ESMF_Calendar) , intent(in) :: cal !< ESMF calendar
349  integer , intent(in), optional :: tod !< time of day in [sec]
350  character(len=*) , intent(in), optional :: desc !< description of time to set
351  integer , intent(in), optional :: logunit!< Unit for stdout output
352  integer , intent(out), optional :: rc !< Return code
353 
354  ! local varaibles
355  integer :: yr, mon, day ! Year, month, day as integers
356  integer :: ltod ! local tod
357  character(len=256) :: ldesc ! local desc
358  character(len=*), parameter :: subname = '(TimeInit) '
359  !-------------------------------------------------------------------------------
360 
361  ltod = 0
362  if (present(tod)) ltod = tod
363  ldesc = ''
364  if (present(desc)) ldesc = desc
365 
366  if ( (ymd < 0) .or. (ltod < 0) .or. (ltod > secperday) )then
367  if (present(logunit)) then
368  write(logunit,*) subname//': ERROR yymmdd is a negative number or '// &
369  'time-of-day out of bounds', ymd, ltod
370  endif
371  call esmf_logseterror(esmf_rc_arg_bad, &
372  msg=subname//' yymmdd is negative or time-of-day out of bounds ', &
373  line=__line__, &
374  file=__file__, rctoreturn=rc)
375  return
376  endif
377 
378  call date2ymd (ymd,yr,mon,day)
379 
380  call esmf_timeset( time, yy=yr, mm=mon, dd=day, s=ltod, calendar=cal, rc=rc )
381  if (esmf_logfounderror(rctocheck=rc, msg=esmf_logerr_passthru, &
382  line=__line__, &
383  file=__file__)) &
384  return
385 

References date2ymd(), and secperday.

Referenced by alarminit().

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ optdate

character(len=*), parameter, private mom_cap_time::optdate = "date"
private

Definition at line 28 of file mom_cap_time.F90.

Referenced by alarminit().

◆ optglccouplingperiod

character(len=*), parameter, private mom_cap_time::optglccouplingperiod = "glc_coupling_period"
private

Definition at line 28 of file mom_cap_time.F90.

◆ optifdays0

character(len=*), parameter, private mom_cap_time::optifdays0 = "ifdays0"
private

Definition at line 28 of file mom_cap_time.F90.

Referenced by alarminit().

◆ optmonthly

character(len=*), parameter, private mom_cap_time::optmonthly = "monthly"
private

Definition at line 28 of file mom_cap_time.F90.

Referenced by alarminit().

◆ optnday

character(len=*), parameter, private mom_cap_time::optnday = "nday"
private

Definition at line 28 of file mom_cap_time.F90.

Referenced by alarminit().

◆ optndays

character(len=*), parameter, private mom_cap_time::optndays = "ndays"
private

Definition at line 28 of file mom_cap_time.F90.

Referenced by alarminit().

◆ optnever

character(len=*), parameter, private mom_cap_time::optnever = "never"
private

Definition at line 28 of file mom_cap_time.F90.

Referenced by alarminit().

◆ optnhour

character(len=*), parameter, private mom_cap_time::optnhour = "nhour"
private

Definition at line 28 of file mom_cap_time.F90.

Referenced by alarminit().

◆ optnhours

character(len=*), parameter, private mom_cap_time::optnhours = "nhours"
private

Definition at line 28 of file mom_cap_time.F90.

Referenced by alarminit().

◆ optnminute

character(len=*), parameter, private mom_cap_time::optnminute = "nminute"
private

Definition at line 28 of file mom_cap_time.F90.

Referenced by alarminit().

◆ optnminutes

character(len=*), parameter, private mom_cap_time::optnminutes = "nminutes"
private

Definition at line 28 of file mom_cap_time.F90.

Referenced by alarminit().

◆ optnmonth

character(len=*), parameter, private mom_cap_time::optnmonth = "nmonth"
private

Definition at line 28 of file mom_cap_time.F90.

Referenced by alarminit().

◆ optnmonths

character(len=*), parameter, private mom_cap_time::optnmonths = "nmonths"
private

Definition at line 28 of file mom_cap_time.F90.

Referenced by alarminit().

◆ optnone

character(len=*), parameter, private mom_cap_time::optnone = "none"
private

Definition at line 28 of file mom_cap_time.F90.

28 character(len=*), private, parameter :: &
29  optnone = "none" , &
30  optnever = "never" , &
31  optnsteps = "nsteps" , &
32  optnstep = "nstep" , &
33  optnseconds = "nseconds" , &
34  optnsecond = "nsecond" , &
35  optnminutes = "nminutes" , &
36  optnminute = "nminute" , &
37  optnhours = "nhours" , &
38  optnhour = "nhour" , &
39  optndays = "ndays" , &
40  optnday = "nday" , &
41  optnmonths = "nmonths" , &
42  optnmonth = "nmonth" , &
43  optnyears = "nyears" , &
44  optnyear = "nyear" , &
45  optmonthly = "monthly" , &
46  optyearly = "yearly" , &
47  optdate = "date" , &
48  optifdays0 = "ifdays0" , &
49  optglccouplingperiod = "glc_coupling_period"

Referenced by alarminit().

◆ optnsecond

character(len=*), parameter, private mom_cap_time::optnsecond = "nsecond"
private

Definition at line 28 of file mom_cap_time.F90.

Referenced by alarminit().

◆ optnseconds

character(len=*), parameter, private mom_cap_time::optnseconds = "nseconds"
private

Definition at line 28 of file mom_cap_time.F90.

Referenced by alarminit().

◆ optnstep

character(len=*), parameter, private mom_cap_time::optnstep = "nstep"
private

Definition at line 28 of file mom_cap_time.F90.

Referenced by alarminit().

◆ optnsteps

character(len=*), parameter, private mom_cap_time::optnsteps = "nsteps"
private

Definition at line 28 of file mom_cap_time.F90.

Referenced by alarminit().

◆ optnyear

character(len=*), parameter, private mom_cap_time::optnyear = "nyear"
private

Definition at line 28 of file mom_cap_time.F90.

Referenced by alarminit().

◆ optnyears

character(len=*), parameter, private mom_cap_time::optnyears = "nyears"
private

Definition at line 28 of file mom_cap_time.F90.

Referenced by alarminit().

◆ optyearly

character(len=*), parameter, private mom_cap_time::optyearly = "yearly"
private

Definition at line 28 of file mom_cap_time.F90.

Referenced by alarminit().

◆ secperday

integer, parameter mom_cap_time::secperday = 86400
private

Definition at line 52 of file mom_cap_time.F90.

52 integer, parameter :: SecPerDay = 86400 ! Seconds per day

Referenced by timeinit().

◆ u_file_u

character(len=*), parameter mom_cap_time::u_file_u = __FILE__
private

Definition at line 53 of file mom_cap_time.F90.

53 character(len=*), parameter :: u_FILE_u = &
54  __file__