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 17:57:11 |  | 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    11289600 : 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    11289600 :    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    11289600 :    yr  = ymd / 10000
         236    11289600 :    mon = (ymd - yr*10000) / 100
         237    11289600 :    day =  ymd - yr*10000 - mon*100
         238             :    call ESMF_TimeSet( TimeSetymd, yy=yr, mm=mon, dd=day, s=tod, &
         239    11289600 :                       calendar=tm_cal, rc=rc)
         240    11289600 :    call chkrc(rc, sub//': error return from ESMF_TimeSet: setting '//trim(desc))
         241    79027200 : end function TimeSetymd
         242             :
         243             : !=========================================================================================
         244             :
         245   294655488 : 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   294655488 :        .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   294488064 :      useday = day
         269             :   endif
         270             :
         271   294655488 :   call ESMF_TimeSet( date, yy=year, mm=month, dd=useday, s=sec, calendar=tm_cal, rc=rc)
         272             :
         273   294655488 :   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   294655488 :   call ESMF_ClockGet(tm_clock, refTime=ref_date, rc=rc )
         278   294655488 :   call chkrc(rc, sub//': error return from ESMF_ClockGet for set_time_float_from_date')
         279             :
         280   294655488 :   diff = date - ref_date
         281             :
         282   294655488 :   call ESMF_TimeIntervalGet( diff, d_r8=time, rc=rc)
         283   294655488 :   call chkrc(rc, sub//': error return from ESMF_TimeIntervalGet for set_time_float_from_date')
         284             :
         285  9428975616 : endsubroutine set_time_float_from_date
         286             :
         287             : !=========================================================================================
         288             :
         289      738816 : 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      738816 :   call ESMF_ClockGet(tm_clock, refTime=ref_date, rc=rc )
         307      738816 :   call chkrc(rc, sub//': error return from ESMF_ClockGet for rset_date_from_time_float')
         308             :
         309      738816 :   call ESMF_TimeIntervalSet( diff, d_r8=time, rc=rc)
         310             :
         311      738816 :   call chkrc(rc, sub//': error return from ESMF_TimeIntervalSet for set_date_from_time_float')
         312             :
         313      738816 :   date = ref_date + diff
         314             :
         315      738816 :   call ESMF_TimeGet( date, yy=year, mm=month, dd=day, s=sec, rc=rc)
         316      738816 :   call chkrc(rc, sub//': error return from ESMF_TimeGet for set_date_from_time_float')
         317             :
         318    23642112 : endsubroutine set_date_from_time_float
         319             :
         320             : !=========================================================================================
         321             :
         322   294655488 : logical function is_leapyear( yr )
         323             :   integer, intent(in) :: yr
         324   294655488 :   is_leapyear = (mod(yr, 400) == 0 .or. mod(yr,100) /= 0) .and. mod(yr,4)==0
         325   294655488 : 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     4710962 : 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     4710962 :    call ESMF_ClockGet(tm_clock, timeStep=step_size, rc=rc)
         527     4710962 :    call chkrc(rc, sub//': error return from ESMF_ClockGet')
         528     4710962 :    call ESMF_TimeIntervalGet(step_size, s=get_step_size, rc=rc)
         529     4710962 :    call chkrc(rc, sub//': error return from ESMF_ClockTimeIntervalGet')
         530             :
         531    94219240 : end function get_step_size
         532             : !=========================================================================================
         533             :
         534   109257722 : 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   109257722 :    call ESMF_ClockGet(tm_clock, advanceCount=step_no, rc=rc)
         545   109257722 :    call chkrc(rc, sub//': error return from ESMF_ClockGet')
         546   109257722 :    get_nstep = step_no
         547             :
         548   109257722 : end function get_nstep
         549             : !=========================================================================================
         550             :
         551    11783580 : 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    11783580 :    call ESMF_ClockGet( tm_clock, currTime=date, rc=rc )
         575    11783580 :    call chkrc(rc, sub//': error return from ESMF_ClockGet')
         576             :
         577    11783580 :    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    11783580 :    call ESMF_TimeGet(date, yy=yr, mm=mon, dd=day, s=tod, rc=rc)
         590    11783580 :    call chkrc(rc, sub//': error return from ESMF_TimeGet')
         591             :
         592   306373080 : 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    24583008 : 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    24583008 :    call ESMF_ClockGet( tm_clock, currTime=date, rc=rc )
         857    24583008 :    call chkrc(rc, sub//': error return from ESMF_ClockGet')
         858             :
         859    24583008 :    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    24583008 :    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    24583008 :    call ESMF_TimeGet( date, dayOfYear_r8=get_curr_calday, rc=rc )
         884    24583008 :    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    24583008 :         .and. (timemgr_is_caltype(trim(shr_cal_gregorian)))) then
         897           0 :       get_curr_calday = get_curr_calday - 1.0_r8
         898             :    endif
         899             :
         900    24583008 :    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  1106235360 : 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       18432 : 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       18432 :    date = TimeSetymd( ymd, tod, "get_calday" )
         964       18432 :    call ESMF_TimeGet( date, dayOfYear_r8=get_calday, rc=rc )
         965       18432 :    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       18432 :         .and. (timemgr_is_caltype(trim(shr_cal_gregorian)))) then
         978           0 :       get_calday = get_calday - 1.0_r8
         979             :    endif
         980             :
         981       18432 :    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      129024 : 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    24601440 : 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    24601440 :    timemgr_is_caltype = ( to_upper(trim(calendar)) == to_upper(trim(cal_in)) )
        1023             :
        1024    24601440 : 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     8967456 : 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     8967456 :    call ESMF_ClockGet( tm_clock, advanceCount=step_no, rc=rc )
        1078     8967456 :    call chkrc(rc, sub//': error return from ESMF_ClockGet')
        1079     8967456 :    nstep = step_no
        1080     8967456 :    is_first_step = (nstep == 0)
        1081             :
        1082     8967456 : end function is_first_step
        1083             : !=========================================================================================
        1084             :
        1085  5979213864 : logical function is_first_restart_step()
        1086             :
        1087             : ! Return true on first step of restart run only.
        1088             :
        1089             : !-----------------------------------------------------------------------------------------
        1090             :
        1091  5979213864 :    is_first_restart_step = tm_first_restart_step
        1092             :
        1093  5979213864 : 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     5632512 : 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     5632512 :    date1 = TimeSetymd( ymd1, tod1, "date1" )
        1155     5632512 :    date2 = TimeSetymd( ymd2, tod2, "date2" )
        1156     5632512 :    diff = date2 - date1
        1157     5632512 :    call ESMF_TimeIntervalGet( diff, d_r8=days, rc=rc )
        1158     5632512 :    call chkrc(rc, sub//': error return from ESMF_TimeIntervalGet')
        1159             :
        1160   180240384 : 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   815778738 : subroutine chkrc(rc, mes)
        1249             :    integer, intent(in)          :: rc   ! return code from time management library
        1250             :    character(len=*), intent(in) :: mes  ! error message
        1251   815778738 :    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