LCOV - code coverage report
Current view: top level - utils - time_manager.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 202 357 56.6 %
Date: 2024-12-17 22:39:59 Functions: 24 36 66.7 %

          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

Generated by: LCOV version 1.14