FV3 Bundle
time_interp.F90
Go to the documentation of this file.
1 !***********************************************************************
2 !* GNU Lesser General Public License
3 !*
4 !* This file is part of the GFDL Flexible Modeling System (FMS).
5 !*
6 !* FMS is free software: you can redistribute it and/or modify it under
7 !* the terms of the GNU Lesser General Public License as published by
8 !* the Free Software Foundation, either version 3 of the License, or (at
9 !* your option) any later version.
10 !*
11 !* FMS is distributed in the hope that it will be useful, but WITHOUT
12 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 !* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 !* for more details.
15 !*
16 !* You should have received a copy of the GNU Lesser General Public
17 !* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
18 !***********************************************************************
19 
21 
22 ! <CONTACT EMAIL="Bruce.Wyman@noaa.gov">
23 ! Bruce Wyman
24 ! </CONTACT>
25 
26 ! <HISTORY SRC="http://www.gfdl.noaa.gov/fms-cgi-bin/cvsweb.cgi/FMS/"/>
27 
28 ! <OVERVIEW>
29 ! Computes a weight and dates/indices for linearly interpolating between two dates.
30 ! </OVERVIEW>
31 
32 ! <DESCRIPTION>
33 ! A time type is converted into two consecutive dates plus
34 ! a fraction representing the distance between the dates.
35 ! This information can be used to interpolate between the dates.
36 ! The dates may be expressed as years, months, or days or
37 ! as indices in an array.
38 ! </DESCRIPTION>
39 
40 ! <PUBLIC>
41 ! Description summarizing public interface.
42 ! </PUBLIC>
43 
44 !-----------------------------------------------------------------------
45 
50  operator(+), operator(-), operator(>), &
51  operator(<), operator( // ), operator( / ), &
52  operator(>=), operator(<=), operator( * ), &
53  operator(==), print_date, print_time,&
55 
56 use fms_mod, only: write_version_number, &
57  error_mesg, fatal, stdout, stdlog, &
58  open_namelist_file, close_file, check_nml_error, &
60 use mpp_mod, only: input_nml_file
61 
62 implicit none
63 private
64 
65 !-----------------------------------------------------------------------
66 
68 
69 ! <INTERFACE NAME="time_interp">
70 
71 ! <OVERVIEW>
72 ! Returns a weight and dates or indices for interpolating between two dates. The
73 ! interface fraction_of_year is provided for backward compatibility with the
74 ! previous version.
75 ! </OVERVIEW>
76 ! <DESCRIPTION>
77 ! Returns weight by interpolating Time between Time1 and Time2.
78 ! i.e. weight = (Time-Time1)/(Time2-Time1)
79 ! Time1 and Time2 may be specified by any of several different ways,
80 ! which is the reason for multiple interfaces.
81 
82 ! If Time1 and Time2 are the begining and end of the year in which
83 ! Time falls, use first interface.
84 
85 ! If Time1 and Time2 fall on year boundaries, use second interface.
86 
87 ! If Time1 and Time2 fall on month boundaries, use third.
88 
89 ! If Time1 and Time2 fall on day boundaries, use fourth.
90 
91 ! If Time1 and Time2 are consecutive elements of an assending list, use fifth.
92 ! The fifth also returns the indices of Timelist between which Time falls.
93 
94 ! The sixth interface is for cyclical data. Time_beg and Time_end specify the
95 ! begining and end of a repeating period. In this case:
96 ! weight = (Time_adjusted - Time1) / (Time2 - Time1)
97 ! Where:
98 ! Time1 = Timelist(index1)
99 ! Time2 = Timelist(index2)
100 ! Time_adjusted = Time - N*Period
101 ! Period = Time_end-Time_beg
102 ! N is between (Time-Time_end)/Period and (Time-Time_beg)/Period
103 ! That is, N is the integer that results in Time_adjusted that is between Time_beg and Time_end.
104 !
105 ! </DESCRIPTION>
106 ! <TEMPLATE>
107 ! 1. call time_interp( Time, weight )
108 ! </TEMPLATE>
109 ! <TEMPLATE>
110 ! 2. call time_interp( Time, weight, year1, year2 )
111 ! </TEMPLATE>
112 ! <TEMPLATE>
113 ! 3. call time_interp( Time, weight, year1, year2, month1, month2 )
114 ! </TEMPLATE>
115 ! <TEMPLATE>
116 ! 4. call time_interp( Time, weight, year1, year2, month1, month2, day1, day2 )
117 ! </TEMPLATE>
118 ! <TEMPLATE>
119 ! 5. call time_interp( Time, Timelist, weight, index1, index2 [, modtime] )
120 ! </TEMPLATE>
121 ! <TEMPLATE>
122 ! 6. call time_interp( Time, Time_beg, Time_end, Timelist, weight, index1, index2 [,correct_leap_year_inconsistency])
123 ! </TEMPLATE>
124 ! <IN NAME="Time">
125 ! The time at which the the weight is computed.
126 ! </IN>
127 ! <IN NAME="Time_beg">
128 ! For cyclical interpolation: Time_beg specifies the begining time of a cycle.
129 ! </IN>
130 ! <IN NAME="Time_end">
131 ! For cyclical interpolation: Time_end specifies the ending time of a cycle.
132 ! </IN>
133 ! <IN NAME="Timelist">
134 ! For cyclical interpolation: Timelist is an array of times between Time_beg and Time_end.
135 ! Must be monotonically increasing.
136 ! </IN>
137 ! <IN NAME="modtime">
138 ! </IN>
139 ! <IN NAME="index1">
140 ! Timelist(index1) = The largest value of Timelist which is less than mod(Time,Time_end-Time_beg)
141 ! </IN>
142 ! <IN NAME="index2">
143 ! Timelist(index2) = The smallest value of Timelist which is greater than mod(Time,Time_end-Time_beg)
144 ! </IN>
145 ! <IN NAME="correct_leap_year_inconsistency">
146 ! Turns on a kluge for an inconsistency which may occur in a special case.
147 ! When the modulo time period (i.e. Time_end - Time_beg) is a whole number of years
148 ! and is not a multiple of 4, and the calendar in use has leap years, then it is
149 ! likely that the interpolation will involve mapping a common year onto a leap year.
150 ! In this case it is often desirable, but not absolutely necessary, to use data for
151 ! Feb 28 of the leap year when it is mapped onto a common year.
152 ! To turn this on, set correct_leap_year_inconsistency=.true.
153 ! </IN>
154 ! <OUT NAME="weight">
155 ! weight = (mod(Time,Time_end-Time_beg) - Timelist(index1)) / (Timelist(index2) - Timelist(index1))
156 ! </OUT>
157 ! <OUT NAME="year1"> </OUT>
158 ! <OUT NAME="year2"> </OUT>
159 ! <OUT NAME="month1"> </OUT>
160 ! <OUT NAME="month2"> </OUT>
161 ! <OUT NAME="day1"> </OUT>
162 ! <OUT NAME="day2"> </OUT>
163 ! <OUT NAME="index1"> </OUT>
164 ! <OUT NAME="index2"> </OUT>
165 ! <ERROR MSG="input time list not ascending order" STATUS="ERROR">
166 ! The list of input time types must have ascending dates.
167 ! </ERROR>
168 ! <ERROR MSG="modulo months must have same length" STATUS="ERROR">
169 ! The length of the current month for input Time and Time_list
170 ! must be the same when using the modulo month option. The
171 ! modulo month option is available but not supported.
172 ! </ERROR>
173 ! <ERROR MSG="invalid value for argument modtime" STATUS="ERROR">
174 ! The optional argument modtime must have a value set by one
175 ! of the public parameters: NONE, YEAR, MONTH, DAY. The
176 ! MONTH and DAY options are available but not supported.
177 ! </ERROR>
178 ! <ERROR MSG="period of list exceeds modulo period" STATUS="ERROR">
179 ! The difference between the last and first values in the input
180 ! Time list/array exceeds the length of the modulo period.
181 ! </ERROR>
182 ! <ERROR MSG="time before range of list or time after range of list" STATUS="ERROR">
183 ! The difference between the last and first values in the input
184 ! These errors occur when you are not using a modulo axis and
185 ! the input Time occurs before the first value in the Time
186 ! list/array or after the last value in the Time list/array.
187 ! </ERROR>
188 ! <NOTE>
189 ! Examples:
190 ! <PRE>
191 ! Time: Jan 01 00z weight = 0.0
192 ! Time: Jul 01 weight ~ 0.5
193 ! Time: Dec 31 23z weight ~ 1.0
194 ! </PRE>
195 ! </NOTE>
196 
197 interface time_interp
198  module procedure time_interp_frac, time_interp_year, &
201 end interface
202 ! </INTERFACE>
203 
204 integer, public, parameter :: none=0, year=1, month=2, day=3
205 
206 !-----------------------------------------------------------------------
207 
208  integer, parameter :: secmin = 60, minhour = 60, hourday = 24, &
209  sechour = secmin*minhour, &
211 
212  integer, parameter :: monyear = 12
213  integer, parameter :: halfday = secday/2
214 
215  integer :: yrmod, momod, dymod
216  logical :: mod_leapyear
217 
218 ! Include variable "version" to be written to log file.
219 #include<file_version.h>
220 
221  logical :: module_is_initialized=.false.
222  logical :: perthlike_behavior=.false.
223 
224  namelist / time_interp_nml / perthlike_behavior
225 
226 contains
227 
228 
229  subroutine time_interp_init()
230  integer :: ierr, io, namelist_unit, logunit
231 
232  if ( module_is_initialized ) return
233 
234 #ifdef INTERNAL_FILE_NML
235  read (input_nml_file, time_interp_nml, iostat=io)
236  ierr = check_nml_error(io, 'time_interp_nml')
237 #else
238  namelist_unit = open_namelist_file()
239  ierr=1
240  do while (ierr /= 0)
241  read(namelist_unit, nml=time_interp_nml, iostat=io, end=20)
242  ierr = check_nml_error(io, 'time_interp_nml')
243  enddo
244  20 call close_file (namelist_unit)
245 #endif
246 
247  call write_version_number("TIME_INTERP_MOD", version)
248  logunit = stdlog()
249  write(logunit,time_interp_nml)
250 
251  module_is_initialized = .true.
252 
253  end subroutine time_interp_init
254 
255 !#######################################################################
256 
257 ! <SUBROUTINE NAME="time_interp_frac" INTERFACE="time_interp">
258 ! <IN NAME="Time" TYPE="time_type" > </IN>
259 ! <OUT NAME="weight" TYPE="real"> </OUT>
260 ! </SUBROUTINE>
261 ! returns the fractional time into the current year
262 
263  subroutine time_interp_frac ( Time, weight )
265  type(time_type), intent(in) :: Time
266  real , intent(out) :: weight
267 
268  integer :: year, month, day, hour, minute, second
269  type(time_type) :: Year_beg, Year_end
270 
271 
272  if ( .not. module_is_initialized ) call time_interp_init
273 
274 ! ---- compute fractional time of year -----
275 
276  call get_date (time, year, month, day, hour, minute, second)
277 
278  year_beg = set_date(year , 1, 1)
279  year_end = set_date(year+1, 1, 1)
280 
281  weight = (time - year_beg) // (year_end - year_beg)
282 
283  end subroutine time_interp_frac
284 
285 !#######################################################################
286 ! <SUBROUTINE NAME="fraction_of_year">
287 ! <OVERVIEW>
288 ! Wrapper for backward compatibility
289 ! </OVERVIEW>
290 ! </SUBROUTINE>
291 
292  function fraction_of_year (Time)
293  type(time_type), intent(in) :: time
294  real :: fraction_of_year
295 
296  call time_interp_frac ( time, fraction_of_year )
297 
298  end function fraction_of_year
299 
300 !#######################################################################
301 ! <SUBROUTINE NAME="time_interp_year" INTERFACE="time_interp">
302 ! <IN NAME="Time" TYPE="time_type" > </IN>
303 ! <OUT NAME="weight" TYPE="real"> </OUT>
304 ! <OUT NAME="year1" TYPE="integer"> </OUT>
305 ! <OUT NAME="year2" TYPE="integer"> </OUT>
306 ! </SUBROUTINE>
307 ! returns fractional time between mid points of consecutive years
308 
309  subroutine time_interp_year ( Time, weight, year1, year2 )
311  type(time_type), intent(in) :: Time
312  real , intent(out) :: weight
313  integer , intent(out) :: year1, year2
314 
315  integer :: year, month, day, hour, minute, second
316  type(time_type) :: mid_year, mid_year1, mid_year2
317 
318 
319  if ( .not. module_is_initialized ) call time_interp_init()
320 
321  call get_date (time, year, month, day, hour, minute, second)
322 
323  ! mid point of current year
324  mid_year = year_midpt(year)
325 
326  if ( time >= mid_year ) then
327  ! current time is after mid point of current year
328  year1 = year
329  year2 = year+1
330  mid_year2 = year_midpt(year2)
331  weight = (time - mid_year) // (mid_year2 - mid_year)
332  else
333  ! current time is before mid point of current year
334  year2 = year
335  year1 = year-1
336  mid_year1 = year_midpt(year1)
337  weight = (time - mid_year1) // (mid_year - mid_year1)
338  endif
339 
340  end subroutine time_interp_year
341 
342 !#######################################################################
343 ! <SUBROUTINE NAME="time_interp_month" INTERFACE="time_interp">
344 ! <IN NAME="Time" TYPE="time_type" > </IN>
345 ! <OUT NAME="weight" TYPE="real"> </OUT>
346 ! <OUT NAME="year1" TYPE="integer"> </OUT>
347 ! <OUT NAME="year2" TYPE="integer"> </OUT>
348 ! <OUT NAME="month1" TYPE="integer"> </OUT>
349 ! <OUT NAME="month2" TYPE="integer"> </OUT>
350 ! </SUBROUTINE>
351 ! returns fractional time between mid points of consecutive months
352 
353  subroutine time_interp_month ( Time, weight, year1, year2, month1, month2 )
355  type(time_type), intent(in) :: Time
356  real , intent(out) :: weight
357  integer , intent(out) :: year1, year2, month1, month2
358 
359  integer :: year, month, day, hour, minute, second, &
360  mid_month, cur_month, mid1, mid2
361 
362  if ( .not. module_is_initialized ) call time_interp_init()
363 
364  call get_date (time, year, month, day, hour, minute, second)
365 
366  ! mid point of current month in seconds
367  mid_month = days_in_month(time) * halfday
368  ! time into current month in seconds
369  cur_month = second + secmin*minute + sechour*hour + secday*(day-1)
370 
371  if ( cur_month >= mid_month ) then
372  ! current time is after mid point of current month
373  year1 = year; month1 = month
374  year2 = year; month2 = month+1
375  if (month2 > monyear) then
376  year2 = year2+1; month2 = 1
377  endif
378  mid1 = mid_month
379  mid2 = days_in_month(set_date(year2,month2,2)) * halfday
380  weight = real(cur_month - mid1) / real(mid1+mid2)
381  else
382  ! current time is before mid point of current month
383  year2 = year; month2 = month
384  year1 = year; month1 = month-1
385  if (month1 < 1) then
386  year1 = year1-1; month1 = monyear
387  endif
388  if (year1>0) then
389  mid1 = days_in_month(set_date(year1,month1,2)) * halfday
390  else
391  ! this can happen if we are at the beginning of year 1. In this case
392  ! use December 0001 to calculate the duration of December 0000.
393  ! This should work for all calendars
394  mid1 = days_in_month(set_date(1,month1,2)) * halfday
395  endif
396  mid2 = mid_month
397  weight = real(cur_month + mid1) / real(mid1+mid2)
398  endif
399 
400  end subroutine time_interp_month
401 
402 !#######################################################################
403 ! <SUBROUTINE NAME="time_interp_day" INTERFACE="time_interp">
404 ! <IN NAME="Time" TYPE="time_type" > </IN>
405 ! <OUT NAME="weight" TYPE="real"> </OUT>
406 ! <OUT NAME="year1" TYPE="integer"> </OUT>
407 ! <OUT NAME="year2" TYPE="integer"> </OUT>
408 ! <OUT NAME="month1" TYPE="integer"> </OUT>
409 ! <OUT NAME="month2" TYPE="integer"> </OUT>
410 ! <OUT NAME="day1" TYPE="integer"> </OUT>
411 ! <OUT NAME="day2" TYPE="integer"> </OUT>
412 ! </SUBROUTINE>
413 ! returns fractional time between mid points of consecutive days
414 
415  subroutine time_interp_day ( Time, weight, year1, year2, month1, month2, day1, day2 )
417  type(time_type), intent(in) :: Time
418  real , intent(out) :: weight
419  integer , intent(out) :: year1, year2, month1, month2, day1, day2
420 
421  integer :: year, month, day, hour, minute, second, sday
422 
423  if ( .not. module_is_initialized ) call time_interp_init()
424 
425  call get_date (time, year, month, day, hour, minute, second)
426 
427  ! time into current day in seconds
428  sday = second + secmin*minute + sechour*hour
429 
430  if ( sday >= halfday ) then
431  ! current time is after mid point of day
432  year1 = year; month1 = month; day1 = day
433  year2 = year; month2 = month; day2 = day + 1
434  weight = real(sday - halfday) / real(secday)
435 
436  if (day2 > days_in_month(time)) then
437  month2 = month2 + 1
438  day2 = 1
439  if (month2 > monyear) then
440  month2 = 1; year2 = year2+1
441  endif
442  endif
443  else
444  ! current time is before mid point of day
445  year2 = year; month2 = month; day2 = day
446  year1 = year; month1 = month; day1 = day - 1
447  weight = real(sday + halfday) / real(secday)
448 
449  if (day1 < 1) then
450  month1 = month1 - 1
451  if (month1 < 1) then
452  month1 = monyear; year1 = year1-1
453  endif
454  day1 = days_in_month(set_date(year1,month1,2))
455  endif
456  endif
457 
458  end subroutine time_interp_day
459 
460 !#######################################################################
461 ! <SUBROUTINE NAME="time_interp_modulo" INTERFACE="time_interp">
462 ! <IN NAME="Time" TYPE="time_type" > </IN>
463 ! <IN NAME="Time_beg" TYPE="time_type"> </IN>
464 ! <IN NAME="Time_end" TYPE="time_type"> </IN>
465 ! <IN NAME="Timelist" TYPE="time_type" DIM="(:)"> </IN>
466 ! <IN NAME="correct_leap_year_inconsistency" TYPE="logical, optional" DEFAULT=".false.">
467 ! Turns on a kluge for an inconsistency which may occur in a special case.
468 ! When the modulo time period (i.e. Time_end - Time_beg) is a whole number of years
469 ! and is not a multiple of 4, and the calendar in use has leap years, then it is
470 ! likely that the interpolation will involve mapping a common year onto a leap year.
471 ! In this case it is often desirable, but not absolutely necessary, to use data for
472 ! Feb 28 of the leap year when it is mapped onto a common year.
473 ! To turn this on, set correct_leap_year_inconsistency=.true. </IN>
474 ! <OUT NAME="weight" TYPE="real"> </OUT>
475 ! <OUT NAME="index1" TYPE="real"> </OUT>
476 ! <OUT NAME="index2" TYPE="real"> </OUT>
477 ! </SUBROUTINE>
478 
479 subroutine time_interp_modulo(Time, Time_beg, Time_end, Timelist, weight, index1, index2, &
480  correct_leap_year_inconsistency, err_msg)
481 type(time_type), intent(in) :: Time, Time_beg, Time_end, Timelist(:)
482 real , intent(out) :: weight
483 integer , intent(out) :: index1, index2
484 logical, intent(in), optional :: correct_leap_year_inconsistency
485 character(len=*), intent(out), optional :: err_msg
486 
487  type(time_type) :: Period, T
488  integer :: is, ie,i1,i2
489  integer :: ys,ms,ds,hs,mins,ss ! components of the starting date
490  integer :: ye,me,de,he,mine,se ! components of the ending date
491  integer :: yt,mt,dt,ht,mint,st ! components of the current date
492  integer :: dt1 ! temporary value for day
493  integer :: n ! size of Timelist
494  integer :: stdoutunit
495  logical :: correct_lyr, calendar_has_leap_years, do_the_lyr_correction
496 
497  if ( .not. module_is_initialized ) call time_interp_init
498  if( present(err_msg) ) err_msg = ''
499 
500  stdoutunit = stdout()
501  n = size(timelist)
502 
503  if (time_beg>=time_end) then
504  if(fms_error_handler('time_interp_modulo', &
505  'end of the specified time loop interval must be later than its beginning',err_msg)) return
506  endif
507 
508  calendar_has_leap_years = (get_calendar_type() == julian .or. get_calendar_type() == gregorian)
509 
510  period = time_end-time_beg ! period of the time axis
511 
512  if(present(correct_leap_year_inconsistency)) then
513  correct_lyr = correct_leap_year_inconsistency
514  else
515  correct_lyr = .false.
516  endif
517 
518  ! bring the requested time inside the specified time period
519  t = time
520 
521  do_the_lyr_correction = .false.
522 
523  ! Determine if the leap year correction needs to be done.
524  ! It never needs to be done unless 3 conditions are met:
525  ! 1) We are using a calendar with leap years
526  ! 2) optional argument correct_leap_year_inconsistency is present and equals .true.
527  ! 3) The modulo time period is an integer number of years
528  ! If all of these are true then set do_the_lyr_correction to .true.
529 
530  if(calendar_has_leap_years .and. correct_lyr) then
531  call get_date(time_beg,ys,ms,ds,hs,mins,ss)
532  call get_date(time_end,ye,me,de,he,mine,se)
533  if(ms==me.and.ds==de.and.hs==he.and.mins==mine.and.ss==se) then
534  ! whole number of years
535  do_the_lyr_correction = .true.
536  endif
537  endif
538 
539  if(do_the_lyr_correction) then
540  call get_date(t,yt,mt,dt,ht,mint,st)
541  yt = ys+modulo(yt-ys,ye-ys)
542  dt1 = dt
543  ! If it is Feb 29, but we map into a common year, use Feb 28
544  if(mt==2.and.dt==29.and..not.leap_year(set_date(yt,1,1))) dt1=28
545  t = set_date(yt,mt,dt1,ht,mint,st)
546  if (t < time_beg) then
547  ! the requested time is within the first year,
548  ! but before the starting date. So we shift it to the last year.
549  if(mt==2.and.dt==29.and..not.leap_year(set_date(ye,1,1))) dt=28
550  t = set_date(ye,mt,dt,ht,mint,st)
551  endif
552  else
553  do while ( t >= time_end )
554  t = t-period
555  enddo
556  do while ( t < time_beg )
557  t = t+period
558  enddo
559  endif
560 
561  ! find indices of the first and last records in the Timelist that are within
562  ! the requested time period.
563  if (time_end<=timelist(1).or.time_beg>=timelist(n)) then
564  if(get_calendar_type() == no_calendar) then
565  call print_time(time_beg, 'Time_beg' )
566  call print_time(time_end, 'Time_end' )
567  call print_time(timelist(1), 'Timelist(1)' )
568  call print_time(timelist(n), 'Timelist(n)' )
569  else
570  call print_date(time_beg, 'Time_beg' )
571  call print_date(time_end, 'Time_end' )
572  call print_date(timelist(1), 'Timelist(1)' )
573  call print_date(timelist(n), 'Timelist(n)' )
574  endif
575  write(stdoutunit,*)'where n = size(Timelist) =',n
576  if(fms_error_handler('time_interp_modulo', &
577  'the entire time list is outside the specified time loop interval',err_msg)) return
578  endif
579 
580  call bisect(timelist,time_beg,index1=i1,index2=i2)
581  if (i1 < 1) then
582  is = 1 ! Time_beg before lower boundary
583  else if (time_beg == timelist(i1)) then
584  is = i1 ! Time_beg right on the lower boundary
585  else
586  is = i2 ! Time_beg inside the interval or on upper boundary
587  endif
588  call bisect(timelist,time_end,index1=i1,index2=i2)
589  if (time_end > timelist(i1)) then
590  ie = i1
591  else if (time_end == timelist(i1)) then
592  if(time_beg == timelist(is)) then
593  ! Timelist includes time levels at both the lower and upper ends of the period.
594  ! The endpoints of Timelist specify the same point in the cycle.
595  ! This ambiguity is resolved by ignoring the last time level.
596  ie = i1-1
597  else
598  ie = i1
599  endif
600  else
601 ! This should never happen because bisect does not return i1 such that Time_end < Timelist(i1)
602  endif
603  if (is>=ie) then
604  if(get_calendar_type() == no_calendar) then
605  call print_time(time_beg, 'Time_beg =')
606  call print_time(time_end, 'Time_end =')
607  call print_time(timelist(1), 'Timelist(1)=')
608  call print_time(timelist(n), 'Timelist(n)=')
609  else
610  call print_date(time_beg, 'Time_beg =')
611  call print_date(time_end, 'Time_end =')
612  call print_date(timelist(1), 'Timelist(1)=')
613  call print_date(timelist(n), 'Timelist(n)=')
614  endif
615  write(stdoutunit,*)'where n = size(Timelist) =',n
616  write(stdoutunit,*)'is =',is,'ie =',ie
617  if(fms_error_handler('time_interp_modulo', &
618  'error in calculation of time list bounds within the specified time loop interval',err_msg)) return
619  endif
620 
621  ! handle special cases:
622  if( t>=timelist(ie) ) then
623  ! time is after the end of the portion of the time list within the requested period
624  index1 = ie; index2 = is
625  weight = (t-timelist(ie))//(period-(timelist(ie)-timelist(is)))
626  else if (t<timelist(is)) then
627  ! time is before the beginning of the portion of the time list within the requested period
628  index1 = ie; index2 = is
629  weight = 1.0-((timelist(is)-t)//(period-(timelist(ie)-timelist(is))))
630  else
631  call bisect(timelist,t,index1,index2)
632  weight = (t-timelist(index1)) // (timelist(index2)-timelist(index1))
633  endif
634 
635 end subroutine time_interp_modulo
636 
637 !#######################################################################
638 ! given an array of times in ascending order and a specific time returns
639 ! values of index1 and index2 such that the Timelist(index1)<=Time and
640 ! Time<=Timelist(index2), and index2=index1+1
641 ! index1=0, index2=1 or index=n, index2=n+1 are returned to indicate that
642 ! the time is out of range
643 subroutine bisect(Timelist,Time,index1,index2)
644  type(time_type) , intent(in) :: Timelist(:)
645  type(time_type) , intent(in) :: Time
646  integer, optional, intent(out) :: index1, index2
647 
648  integer :: i,il,iu,n,i1,i2
649 
650  n = size(timelist(:))
651 
652  if (time==timelist(1)) then
653  i1 = 1 ; i2 = 2
654  else if (time==timelist(n)) then
655  i1 = n ; i2 = n+1
656  else
657  il = 0; iu=n+1
658  do while(iu-il > 1)
659  i = (iu+il)/2
660  if(timelist(i) > time) then
661  iu = i
662  else
663  il = i
664  endif
665  enddo
666  i1 = il ; i2 = il+1
667  endif
668 
669  if(PRESENT(index1)) index1 = i1
670  if(PRESENT(index2)) index2 = i2
671 end subroutine bisect
672 
673 
674 !#######################################################################
675 ! <SUBROUTINE NAME="time_interp_list" INTERFACE="time_interp">
676 ! <IN NAME="Time" TYPE="time_type" > </IN>
677 ! <IN NAME="Timelist" TYPE="time_type" DIM="(:)"> </IN>
678 ! <OUT NAME="weight" TYPE="real"> </OUT>
679 ! <OUT NAME="index1" TYPE="real"> </OUT>
680 ! <OUT NAME="index2" TYPE="real"> </OUT>
681 ! <IN NAME="modtime" TYPE="integer" > </IN>
682 ! </SUBROUTINE>
683 
684 subroutine time_interp_list ( Time, Timelist, weight, index1, index2, modtime, err_msg )
685 type(time_type) , intent(in) :: Time, Timelist(:)
686 real , intent(out) :: weight
687 integer , intent(out) :: index1, index2
688 integer, optional, intent(in) :: modtime
689 character(len=*), intent(out), optional :: err_msg
690 
691 integer :: n, hr, mn, se, mtime
692 type(time_type) :: T, Ts, Te, Td, Period, Time_mod
693 character(len=:),allocatable :: terr, tserr, teerr
694 
695  if ( .not. module_is_initialized ) call time_interp_init
696 
697  if( present(err_msg) ) err_msg = ''
698 
699  weight = 0.; index1 = 0; index2 = 0
700  n = size(timelist(:))
701 
702 ! setup modular time axis?
703  mtime = none
704  if (present(modtime)) then
705  mtime = modtime
706  time_mod = (timelist(1)+timelist(n))/2
707  call get_date (time_mod, yrmod, momod, dymod, hr, mn, se)
708  mod_leapyear = leap_year(time_mod)
709  endif
710 
711 ! set period for modulo axis
712  select case (mtime)
713  case (none)
714  ! do nothing
715  case (year)
716  period = set_time(0,days_in_year(time_mod))
717  case (month)
718  ! month length must be equal
719  if (days_in_month(time_mod) /= days_in_month(time)) then
720  if(fms_error_handler('time_interp_list','modulo months must have same length',err_msg)) return
721  endif
722  period = set_time(0,days_in_month(time_mod))
723  case (day)
724  period = set_time(0,1)
725  case default
726  if(fms_error_handler('time_interp_list','invalid value for argument modtime',err_msg)) return
727  end select
728 
729 ! If modulo time is in effect and Timelist spans a time interval exactly equal to
730 ! the modulo period, then the endpoints of Timelist specify the same point in the cycle.
731 ! This ambiguity is resolved by ignoring the last time level.
732  if (mtime /= none .and. timelist(size(timelist))-timelist(1) == period) then
733  n = size(timelist) - 1
734  else
735  n = size(timelist)
736  endif
737 
738 ! starting and ending times from list
739  ts = timelist(1)
740  te = timelist(n)
741  td = te-ts
742  t = set_modtime(time,mtime)
743 
744 ! Check that Timelist does not span a time interval greater than the modulo period
745  if (mtime /= none) then
746  if (td > period) then
747  if(fms_error_handler('time_interp_list','period of list exceeds modulo period',err_msg)) return
748  endif
749  endif
750 
751 ! time falls on start or between start and end list values
752  if ( t >= ts .and. t < te ) then
753  call bisect(timelist(1:n),t,index1,index2)
754  weight = (t-timelist(index1)) // (timelist(index2)-timelist(index1))
755 
756 ! time falls before starting list value
757  else if ( t < ts ) then
758  if (mtime == none) then
759  call time_list_error(t,terr)
760  call time_list_error(ts,tserr)
761  call time_list_error(te,teerr)
762  if(fms_error_handler('time_interp_list',&
763  'time '//trim(terr)//' ('//date_to_string(t)//' is before range of list '//trim(tserr)//'-'//trim(teerr)//&
764  '('//date_to_string(ts)//' - '//date_to_string(te)//')',&
765  err_msg)) return
766  deallocate(terr,tserr,teerr)
767  endif
768  td = te-ts
769  weight = 1. - ((ts-t) // (period-td))
770  index1 = n
771  index2 = 1
772 
773 ! time falls on ending list value
774  else if ( t == te ) then
775  if(perthlike_behavior) then
776  weight = 1.0
777  index1 = n-1
778  index2 = n
779  else
780  weight = 0.
781  index1 = n
782  if (mtime == none) then
783  index2 = n
784  else
785  index2 = 1
786  endif
787  endif
788 
789 ! time falls after ending list value
790  else if ( t > te ) then
791  if (mtime == none) then
792  call time_list_error(t,terr)
793  call time_list_error(ts,tserr)
794  call time_list_error(te,teerr)
795  if(fms_error_handler('time_interp_list',&
796  'time '//trim(terr)//' ('//date_to_string(t)//' is after range of list '//trim(tserr)//'-'//trim(teerr)//&
797  '('//date_to_string(ts)//' - '//date_to_string(te)//')',&
798  err_msg)) return
799  deallocate(terr,tserr,teerr)
800  endif
801  td = te-ts
802  weight = (t-te) // (period-td)
803  index1 = n
804  index2 = 1
805  endif
806 
807 end subroutine time_interp_list
808 
809 !#######################################################################
810 ! private routines
811 !#######################################################################
812 
813  function year_midpt (year)
815  integer, intent(in) :: year
816  type(time_type) :: year_midpt, year_beg, year_end
817 
818 
819  year_beg = set_date(year , 1, 1)
820  year_end = set_date(year+1, 1, 1)
821 
822  year_midpt = (year_beg + year_end) / 2
823 
824  end function year_midpt
825 
826 !#######################################################################
827 
828  function month_midpt (year, month)
830  integer, intent(in) :: year, month
831  type(time_type) :: month_midpt, month_beg, month_end
832 
833 ! --- beginning of this month ---
834  month_beg = set_date(year, month, 1)
835 
836 ! --- start of next month ---
837  if (month < 12) then
838  month_end = set_date(year, month+1, 1)
839  else
840  month_end = set_date(year+1, 1, 1)
841  endif
842 
843  month_midpt = (month_beg + month_end) / 2
844 
845  end function month_midpt
846 
847 !#######################################################################
848 
849 function set_modtime (Tin, modtime) result (Tout)
850 type(time_type), intent(in) :: tin
851 integer, intent(in), optional :: modtime
852 type(time_type) :: tout
853 integer :: yr, mo, dy, hr, mn, se, mtime
854 
855  if(present(modtime)) then
856  mtime = modtime
857  else
858  mtime = none
859  endif
860 
861  select case (mtime)
862  case (none)
863  tout = tin
864  case (year)
865  call get_date (tin, yr, mo, dy, hr, mn, se)
866  yr = yrmod
867  ! correct leap year dates
868  if (.not.mod_leapyear .and. mo == 2 .and. dy > 28) then
869  mo = 3; dy = dy-28
870  endif
871  tout = set_date(yr, mo, dy, hr, mn, se)
872  case (month)
873  call get_date (tin, yr, mo, dy, hr, mn, se)
874  yr = yrmod; mo = momod
875  tout = set_date(yr, mo, dy, hr, mn, se)
876  case (day)
877  call get_date (tin, yr, mo, dy, hr, mn, se)
878  yr = yrmod; mo = momod; dy = dymod
879  tout = set_date(yr, mo, dy, hr, mn, se)
880  end select
881 
882 end function set_modtime
883 
884 !#######################################################################
885 
886 subroutine error_handler (string)
887 character(len=*), intent(in) :: string
888 
889  call error_mesg ('time_interp_mod', trim(string), fatal)
890 
891 ! write (*,'(a)') 'ERROR in time_interp: ' // trim(string)
892 ! stop 111
893 
894 end subroutine error_handler
895 
896 !#######################################################################
897 
898 end module time_interp_mod
899 
900 ! <INFO>
901 
902 ! <ERROR MSG="input time list not ascending order" STATUS="">
903 ! The list of input time types must have ascending dates.
904 ! </ERROR> *
905 ! <ERROR MSG="modulo months must have same length" STATUS="">
906 ! The length of the current month for input Time and Time_list
907 ! must be the same when using the modulo month option.
908 ! The modulo month option is available but not supported.
909 ! </ERROR> *
910 ! <ERROR MSG="invalid value for argument modtime" STATUS="">
911 ! The optional argument modtime must have a value set by one
912 ! of the public parameters: NONE, YEAR, MONTH, DAY.
913 ! The MONTH and DAY options are available but not supported.
914 ! </ERROR> *
915 ! <ERROR MSG="period of list exceeds modulo period" STATUS="">
916 ! The difference between the last and first values in the
917 ! input Time list/array exceeds the length of the modulo period.
918 ! </ERROR> *
919 ! <ERROR MSG="time before range of list or time after range of list" STATUS="">
920 ! These errors occur when you are not using a modulo axis and the
921 ! input Time occurs before the first value in the Time list/array
922 ! or after the last value in the Time list/array.
923 ! </ERROR> *
924 ! <NOTE>
925 ! For all routines in this module the calendar type in module
926 ! time_manager must be set.
927 ! </NOTE>
928 ! <NOTE>
929 ! The following private parameters are set by this module:
930 ! <PRE>
931 ! seconds per minute = 60
932 ! minutes per hour = 60
933 ! hours per day = 24
934 ! months per year = 12
935 ! </PRE>
936 ! </NOTE>
937 
938 ! </INFO>
939 
940 #ifdef test_time_interp_
941  program test_time_interp
942  use fms_mod, only: fms_init, fms_end, stdout, stdlog, fatal, mpp_error
946 
947  implicit none
948 
949  integer, parameter :: num_Time=6
950  type(time_type) :: Time_beg, Time_end, Time(num_Time)
951  type(time_type), allocatable, dimension(:) :: Timelist
952  integer :: index1, index2, mo, yr, timelist_len, outunit, ntest, nline
953  real :: weight
954 
955  integer :: nmin, nmax
956 
957  namelist / test_time_interp_nml / timelist_len
958 
959  call fms_init
960  outunit = stdout()
961  call set_calendar_type(julian)
962  call time_interp_init
963 
964  time_beg = set_date(1, 1, 1)
965  time_end = set_date(2, 1, 1)
966  time(1) = time_beg
967  time(2) = set_date(1, 1,16)
968  time(3) = set_date(1, 2, 1)
969  time(4) = set_date(1,12, 1)
970  time(5) = set_date(1,12,16)
971  time(6) = time_end
972 
973 ! Tests with modulo time
974  do nline=1,3
975  if(nline == 1) then
976  allocate(timelist(12))
977  do mo=1,12
978  timelist(mo) = set_date(1, mo, 1)
979  enddo
980  else if(nline == 2) then
981  allocate(timelist(13))
982  do mo=1,12
983  timelist(mo) = set_date(1, mo, 1)
984  enddo
985  timelist(13) = set_date(2, 1, 1)
986  else if(nline == 3) then
987  allocate(timelist(12))
988  do mo=2,12
989  timelist(mo-1) = set_date(1, mo, 1)
990  enddo
991  timelist(12) = set_date(2, 1, 1)
992  endif
993 
994  do ntest=1,num_time
995  call diagram(nline,ntest,modulo_time=.true.)
996  call time_interp(time(ntest), time_beg, time_end, timelist, weight, index1, index2)
997  write(outunit,*) 'time_interp_modulo:'
998  write(outunit,'()')
999  call print_date(time(ntest), 'Time =')
1000  call print_date(time_beg, 'Time_beg =')
1001  call print_date(time_end, 'Time_end =')
1002  call print_date(timelist(1), 'Timelist(1)=')
1003  call print_date(timelist(size(timelist(:))),'Timelist(n)=')
1004  write(outunit,99) index1,index2,weight
1005  write(outunit,'()')
1006 
1007  call time_interp(time(ntest), timelist, weight, index1, index2, modtime=year)
1008  write(outunit,*) 'time_interp_list with modtime=YEAR:'
1009  write(outunit,'()')
1010  call print_date(time(ntest), 'Time =')
1011  call print_date(timelist(1), 'Timelist(1)=')
1012  call print_date(timelist(size(timelist(:))),'Timelist(n)=')
1013  write(outunit,99) index1,index2,weight
1014  enddo
1015  deallocate(timelist)
1016  enddo
1017 
1018 ! Tests without modulo time
1019  do nline=1,3
1020  if(nline == 1) then
1021  allocate(timelist(12))
1022  do mo=1,12
1023  timelist(mo) = set_date(1, mo, 1)
1024  enddo
1025  else if(nline == 2) then
1026  allocate(timelist(13))
1027  do mo=1,12
1028  timelist(mo) = set_date(1, mo, 1)
1029  enddo
1030  timelist(13) = set_date(2, 1, 1)
1031  else if(nline == 3) then
1032  allocate(timelist(12))
1033  do mo=2,12
1034  timelist(mo-1) = set_date(1, mo, 1)
1035  enddo
1036  timelist(12) = set_date(2, 1, 1)
1037  endif
1038 
1039  if(nline == 1) then
1040  nmin = 1; nmax = 4
1041  else if(nline == 2) then
1042  nmin = 1; nmax = num_time
1043  else if(nline == 3) then
1044  nmin = 3; nmax = num_time
1045  endif
1046  do ntest=nmin,nmax
1047  call diagram(nline,ntest,modulo_time=.false.)
1048  call time_interp(time(ntest), timelist, weight, index1, index2, modtime=none)
1049  write(outunit,*) 'time_interp_list with modtime=NONE:'
1050  write(outunit,'()')
1051  call print_date(time(ntest), 'Time =')
1052  call print_date(timelist(1), 'Timelist(1)=')
1053  call print_date(timelist(size(timelist(:))),'Timelist(n)=')
1054  write(outunit,99) index1,index2,weight
1055  enddo
1056  deallocate(timelist)
1057  enddo
1058 
1059 ! More tests with modulo time
1060  time_beg = set_date(1999, 1, 1)
1061  time_end = set_date(2000, 1, 1)
1062  time(1) = set_date(1998, 1, 1)
1063  time(2) = set_date(1998, 2,28)
1064  time(3) = set_date(1998,12,16)
1065  time(4) = set_date(2000, 1, 1)
1066  time(5) = set_date(2000, 2,28)
1067  time(6) = set_date(2000, 2,29)
1068 
1069  allocate(timelist(13))
1070  do mo=1,12
1071  timelist(mo) = set_date(1999, mo, 1)
1072  enddo
1073  timelist(13) = set_date(2000, 1, 1)
1074 
1075  write(outunit,'("<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>",/)')
1076  write(outunit,'()')
1077  write(outunit,*) 'time_interp_modulo with correct_leap_year_inconsistency=.true.'
1078  write(outunit,'()')
1079  write(outunit,'(" Jan 1 1999 Jan 1 2000")')
1080  write(outunit,'(" | |")')
1081  write(outunit,'(" v v")')
1082  write(outunit,'(" x---x---x---x---x---x---x---x---x---x---x---x---x")')
1083  write(outunit,'(" ^ ^")')
1084  write(outunit,'(" | |")')
1085  write(outunit,'(" Time_beg Time_end ")')
1086  write(outunit,'()')
1087 
1088  do ntest=1,num_time
1089  call time_interp(time(ntest), time_beg, time_end, timelist, weight, index1, index2, correct_leap_year_inconsistency=.true.)
1090  call print_date(time(ntest),' Time =')
1091  write(outunit,99) index1,index2,weight
1092  write(outunit,'()')
1093  enddo
1094  deallocate(timelist)
1095 
1096 ! Tests of modulo time and leap year inconsistency
1097  time_beg = set_date(1978, 1, 1)
1098  time_end = set_date(1981, 1, 1)
1099  time(1) = set_date(1976, 2,28)
1100  time(2) = set_date(1976, 2,29)
1101  time(3) = set_date(1976, 3, 1)
1102  time(4) = set_date(1983, 2,28)
1103  time(5) = set_date(1983, 3, 1)
1104  time(6) = set_date(1981, 1, 1)
1105  allocate(timelist(37))
1106  do yr=1978,1980
1107  do mo=1,12
1108  timelist(12*(yr-1978)+mo) = set_date(yr, mo, 1)
1109  enddo
1110  enddo
1111  timelist(37) = set_date(1981, 1, 1)
1112 
1113  write(outunit,'("<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>")')
1114  write(outunit,'()')
1115  write(outunit,*) 'time_interp_modulo with correct_leap_year_inconsistency=.true.'
1116  write(outunit,'()')
1117  write(outunit,'(" Jan 1 1978 Jan 1 1979 Jan 1 1980 Jan 1 1981")')
1118  write(outunit,'(" | | | <---- leap year ----> |")')
1119  write(outunit,'(" v v v v")')
1120  write(outunit,'(" x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x")')
1121  write(outunit,'(" ^ ^")')
1122  write(outunit,'(" | |")')
1123  write(outunit,'(" Time_beg Time_end")')
1124  write(outunit,'()')
1125 
1126  do ntest=1,num_time
1127  call time_interp(time(ntest), time_beg, time_end, timelist, weight, index1, index2, correct_leap_year_inconsistency=.true.)
1128  call print_date(time(ntest),' Time=')
1129  write(outunit,99) index1,index2,weight
1130  write(outunit,'()')
1131  enddo
1132  deallocate(timelist)
1133 
1134  allocate(timelist(12))
1135  timelist( 1) = set_date(1, 1, 16, hour=12) ! Jan midmonth
1136  timelist( 2) = set_date(1, 2, 15, hour= 0) ! Feb midmonth (common year)
1137  timelist( 3) = set_date(1, 3, 16, hour=12) ! Mar midmonth
1138  timelist( 4) = set_date(1, 4, 16, hour= 0) ! Apr midmonth
1139  timelist( 5) = set_date(1, 5, 16, hour=12) ! May midmonth
1140  timelist( 6) = set_date(1, 6, 16, hour= 0) ! Jun midmonth
1141  timelist( 7) = set_date(1, 7, 16, hour=12) ! Jul midmonth
1142  timelist( 8) = set_date(1, 8, 16, hour=12) ! Aug midmonth
1143  timelist( 9) = set_date(1, 9, 16, hour= 0) ! Sep midmonth
1144  timelist(10) = set_date(1, 10, 16, hour=12) ! Oct midmonth
1145  timelist(11) = set_date(1, 11, 16, hour= 0) ! Nov midmonth
1146  timelist(12) = set_date(1, 12, 16, hour=12) ! Dec midmonth
1147  time_beg = set_date(1, 1, 1)
1148  time_end = set_date(2, 1, 1)
1149  call diagram(nline=4, ntest=0, modulo_time=.true.)
1150  do ntest=0,73
1151  time(1) = set_date(1996, 1, 1) + set_time(seconds=0, days=5*ntest)
1152  call print_date(time(1),' Time=')
1153  call time_interp(time(1), timelist, weight, index1, index2, modtime=year)
1154  write(outunit,89) 'time_interp_list with modtime=YEAR: ', index1,index2,weight
1155  call time_interp(time(1), time_beg, time_end, timelist, weight, index1, index2, correct_leap_year_inconsistency=.true.)
1156  write(outunit,89) 'time_interp_modulo: ', index1,index2,weight
1157  write(outunit,'()')
1158  enddo
1159 
1160  99 format(' index1=',i3,' index2=',i3,' weight=',f18.15)
1161  89 format(a20,' index1=',i3,' index2=',i3,' weight=',f18.15)
1162  call fms_end
1163 
1164  contains
1165 
1166  subroutine diagram(nline,ntest,modulo_time)
1167  integer, intent(in) :: nline,ntest
1168  logical, intent(in) :: modulo_time
1169 
1170  write(outunit,'("<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>")')
1171  write(outunit,'()')
1172  if(modulo_time) then
1173  write(outunit,'(" Time_beg Time_end")')
1174  write(outunit,'(" | |")')
1175  write(outunit,'(" v v")')
1176  endif
1177 
1178  if(nline == 1) then
1179  write(outunit,'(" x---x---x---x---x---x---x---x---x---x---x---x----")')
1180  else if(nline == 2) then
1181  write(outunit,'(" x---x---x---x---x---x---x---x---x---x---x---x---x")')
1182  else if(nline == 3) then
1183  write(outunit,'(" ----x---x---x---x---x---x---x---x---x---x---x---x")')
1184  else if(nline == 4) then
1185  write(outunit,'(" --x---x---x---x---x---x---x---x---x---x---x---x--")')
1186  endif
1187 
1188  if(ntest == 1) then
1189  write(outunit,'(" ^") ')
1190  write(outunit,'(" |") ')
1191  write(outunit,'(" Time")')
1192  else if(ntest == 2) then
1193  write(outunit,'(" ^") ')
1194  write(outunit,'(" |") ')
1195  write(outunit,'(" Time")')
1196  else if(ntest == 3) then
1197  write(outunit,'(" ^") ')
1198  write(outunit,'(" |") ')
1199  write(outunit,'(" Time")')
1200  else if(ntest == 4) then
1201  write(outunit,'(" ^") ')
1202  write(outunit,'(" |") ')
1203  write(outunit,'(" Time")')
1204  else if(ntest == 5) then
1205  write(outunit,'(" ^") ')
1206  write(outunit,'(" |") ')
1207  write(outunit,'(" Time")')
1208  else if(ntest == 6) then
1209  write(outunit,'(" ^") ')
1210  write(outunit,'(" |") ')
1211  write(outunit,'(" Time")')
1212  endif
1213  write(outunit,'()')
1214 
1215  end subroutine diagram
1216 
1217  end program test_time_interp
1218 #endif
Definition: fms.F90:20
subroutine, public time_interp_init()
type(time_type) function, public increment_time(Time, seconds, days, ticks, err_msg, allow_neg_inc)
subroutine, public get_date(time, year, month, day, hour, minute, second, tick, err_msg)
integer, parameter, public gregorian
void error_handler(const char *msg)
Definition: mosaic_util.c:55
integer, parameter, public noleap
subroutine time_interp_day(Time, weight, year1, year2, month1, month2, day1, day2)
integer, parameter secmin
subroutine time_interp_year(Time, weight, year1, year2)
logical function, public fms_error_handler(routine, message, err_msg)
Definition: fms.F90:573
integer, parameter, public none
integer, parameter secday
Definition: mpp.F90:39
integer function, public check_nml_error(IOSTAT, NML_NAME)
Definition: fms.F90:658
logical perthlike_behavior
character(len=input_str_length), dimension(:), allocatable, target, public input_nml_file
Definition: mpp.F90:1378
integer, parameter, public month
subroutine, public set_calendar_type(type, err_msg)
integer, parameter, public day
subroutine time_interp_list(Time, Timelist, weight, index1, index2, modtime, err_msg)
subroutine, public fms_init(localcomm)
Definition: fms.F90:353
character(len=15) function, public date_to_string(time, err_msg)
integer, parameter monyear
integer function, public days_in_month(Time, err_msg)
integer, parameter, public julian
subroutine, public time_list_error(T, Terr)
This routine converts the integer tdays to a string.
integer function, public get_calendar_type()
integer, parameter hourday
integer, parameter minhour
integer, parameter halfday
type(time_type) function year_midpt(year)
subroutine, public time_manager_init()
type(time_type) function set_modtime(Tin, modtime)
real function, public fraction_of_year(Time)
integer, parameter, public year
logical module_is_initialized
integer, parameter, public no_calendar
logical mod_leapyear
subroutine time_interp_modulo(Time, Time_beg, Time_end, Timelist, weight, index1, index2, correct_leap_year_inconsistency, err_msg)
logical function, public leap_year(Time, err_msg)
subroutine, public fms_end()
Definition: fms.F90:476
type(time_type) function, public real_to_time_type(x, err_msg)
subroutine time_interp_month(Time, weight, year1, year2, month1, month2)
subroutine bisect(Timelist, Time, index1, index2)
real(double_kind) function, public time_type_to_real(time)
integer, parameter sechour
subroutine time_interp_frac(Time, weight)
type(time_type) function month_midpt(year, month)
integer function, public days_in_year(Time)
subroutine, public error_mesg(routine, message, level)
Definition: fms.F90:529
subroutine, public print_time(Time, str, unit)
subroutine, public print_date(Time, str, unit)