Revision f7b2f3fd43c140a005e5d215dfcbc131fe9c1c0f authored by Ryan Knox on 12 October 2021, 14:49:52 UTC, committed by Ryan Knox on 12 October 2021, 14:49:52 UTC
1 parent bf910e9
Raw File
seq_timemgr_mod.F90
!===============================================================================
!
! !MODULE: seq_timemgr_mod --- Time-manager module
!
! !DESCRIPTION:
!
!     A module to create derived types to manage time and clock information
!     for use with CIME drivers and models.
!
! !REMARKS:
!
! !REVISION HISTORY:
!     2005-Nov-11 - E. Kluzek - creation as eshr_timemgr_mod
!     2007-Sep-12 - T. Craig - extended
!     2007-Oct-05 - T. Craig - refactored to support concurrent models
!     2007-Nov-15 - T. Craig - refactored for ccsm4 and renamed seq_timemgr_mod
!
! !INTERFACE: ------------------------------------------------------------------

module seq_timemgr_mod

  ! !USES:
  use ESMF
  use shr_cal_mod
  use SHR_KIND_mod,     only: SHR_KIND_IN, SHR_KIND_R8, SHR_KIND_CS, &
       SHR_KIND_CL, SHR_KIND_I8
  use seq_comm_mct,     only: logunit, loglevel, seq_comm_iamin, CPLID, &
       seq_comm_gloroot, seq_comm_iamroot
  use shr_sys_mod,      only: shr_sys_abort, shr_sys_flush

  implicit none

  private    ! default private

  ! ! PUBLIC TYPES:

  public :: seq_timemgr_type         ! Wrapped clock object

  ! ! PUBLIC MEMBER FUNCTIONS:

  ! --- Clock object methods --------------------------------------------------
  public :: seq_timemgr_clockInit         ! Setup the sync clock
  public :: seq_timemgr_clockAdvance      ! Advance the sync clock
  public :: seq_timemgr_clockPrint        ! Print sync clock information

  public :: seq_timemgr_EClockGetData     ! Get data from an ESMF clock

  public :: seq_timemgr_EClockDateInSync  ! compare EClock to ymd/tod
  public :: seq_timemgr_alarmSetOn        ! Turn an alarm on
  public :: seq_timemgr_alarmSetOff       ! Turn an alarm off
  public :: seq_timemgr_alarmIsOn         ! Is an alarm ringing
  public :: seq_timemgr_ETimeInit         ! Create ESMF_Time object
  public :: seq_timemgr_ETimeGet          ! Query ESMF_Time object

  ! --- For usability, built on interfaces above ---
  public :: seq_timemgr_restartAlarmIsOn    ! Is a restart alarm ringing
  public :: seq_timemgr_stopAlarmIsOn       ! Is a stop alarm ringing
  public :: seq_timemgr_historyAlarmIsOn    ! Is a history alarm ringing
  public :: seq_timemgr_pauseAlarmIsOn      ! Is a pause alarm ringing
  ! --- ESP components need to know about the state of other components
  public :: seq_timemgr_pause_active        ! Pause/resume is enabled
  public :: seq_timemgr_pause_component_index ! Index of named component
  public :: seq_timemgr_pause_component_active ! .true. is comp should pause

  ! --- Alert components if they need to do post-data assimilation processing
  public :: seq_timemgr_data_assimilation_active ! .true. do post-DA

  ! ! PUBLIC PARAMETERS:

  integer(SHR_KIND_IN),public :: seq_timemgr_histavg_type
  integer(SHR_KIND_IN),public,parameter :: seq_timemgr_type_other  = -1
  integer(SHR_KIND_IN),public,parameter :: seq_timemgr_type_never  = 1
  integer(SHR_KIND_IN),public,parameter :: seq_timemgr_type_nhour  = 2
  integer(SHR_KIND_IN),public,parameter :: seq_timemgr_type_nday   = 3
  integer(SHR_KIND_IN),public,parameter :: seq_timemgr_type_nmonth = 4
  integer(SHR_KIND_IN),public,parameter :: seq_timemgr_type_nyear  = 5

  character(SHR_KIND_CS),public,parameter :: seq_timemgr_noleap    = shr_cal_noleap
  character(SHR_KIND_CS),public,parameter :: seq_timemgr_gregorian = shr_cal_gregorian

  !  These are public but declared in the private area for clarity

  !  clocknames:
  !   character(len=*),public,parameter :: &
  !      seq_timemgr_clock_drv
  !      seq_timemgr_clock_atm
  !      seq_timemgr_clock_lnd
  !      seq_timemgr_clock_rof
  !      seq_timemgr_clock_ocn
  !      seq_timemgr_clock_ice
  !      seq_timemgr_clock_glc
  !      seq_timemgr_clock_wav
  !      seq_timemgr_clock_esp

  !  alarmnames:
  !   character(len=*),public,parameter :: &
  !      seq_timemgr_alarm_restart
  !      seq_timemgr_alarm_run
  !      seq_timemgr_alarm_stop
  !      seq_timemgr_alarm_datestop
  !      seq_timemgr_alarm_history
  !      seq_timemgr_alarm_atmrun
  !      seq_timemgr_alarm_lndrun
  !      seq_timemgr_alarm_rofrun
  !      seq_timemgr_alarm_ocnrun
  !      seq_timemgr_alarm_icerun
  !      seq_timemgr_alarm_glcrun
  !      seq_timemgr_alarm_glcrun_avg
  !      seq_timemgr_alarm_wavrun
  !      seq_timemgr_alarm_esprun
  !      seq_timemgr_alarm_ocnnext
  !      seq_timemgr_alarm_tprof
  !      seq_timemgr_alarm_histavg
  !      seq_timemgr_alarm_pause
  !      seq_timemgr_alarm_barrier

  private:: seq_timemgr_alarmGet
  private:: seq_timemgr_alarmInit
  private:: seq_timemgr_EClockInit
  private:: seq_timemgr_ESMFDebug
  private:: seq_timemgr_ESMFCodeCheck

  character(len=*), private, parameter :: &
       seq_timemgr_optNONE           = "none"      , &
       seq_timemgr_optNever          = "never"     , &
       seq_timemgr_optNSteps         = "nsteps"    , &
       seq_timemgr_optNStep          = "nstep"     , &
       seq_timemgr_optNSeconds       = "nseconds"  , &
       seq_timemgr_optNSecond        = "nsecond"   , &
       seq_timemgr_optNMinutes       = "nminutes"  , &
       seq_timemgr_optNMinute        = "nminute"   , &
       seq_timemgr_optNHours         = "nhours"    , &
       seq_timemgr_optNHour          = "nhour"     , &
       seq_timemgr_optNDays          = "ndays"     , &
       seq_timemgr_optNDay           = "nday"      , &
       seq_timemgr_optNMonths        = "nmonths"   , &
       seq_timemgr_optNMonth         = "nmonth"    , &
       seq_timemgr_optNYears         = "nyears"    , &
       seq_timemgr_optNYear          = "nyear"     , &
       seq_timemgr_optMonthly        = "monthly"   , &
       seq_timemgr_optYearly         = "yearly"    , &
       seq_timemgr_optDate           = "date"      , &
       seq_timemgr_optIfdays0        = "ifdays0"   , &
       seq_timemgr_optEnd            = "end"       , &
       seq_timemgr_optGLCCouplingPeriod = "glc_coupling_period"

  integer(SHR_KIND_IN),private,parameter :: &
       seq_timemgr_nclock_drv  = 1, &
       seq_timemgr_nclock_atm  = 2, &
       seq_timemgr_nclock_lnd  = 3, &
       seq_timemgr_nclock_ocn  = 4, &
       seq_timemgr_nclock_ice  = 5, &
       seq_timemgr_nclock_glc  = 6, &
       seq_timemgr_nclock_wav  = 7, &
       seq_timemgr_nclock_rof  = 8, &
       seq_timemgr_nclock_iac  = 9, &
       seq_timemgr_nclock_esp  = 10

  integer(SHR_KIND_IN),private,parameter :: max_clocks = 10
  character(len=*),public,parameter :: &
       seq_timemgr_clock_drv  = 'seq_timemgr_clock_drv' , &
       seq_timemgr_clock_atm  = 'seq_timemgr_clock_atm' , &
       seq_timemgr_clock_lnd  = 'seq_timemgr_clock_lnd' , &
       seq_timemgr_clock_ocn  = 'seq_timemgr_clock_ocn' , &
       seq_timemgr_clock_ice  = 'seq_timemgr_clock_ice' , &
       seq_timemgr_clock_glc  = 'seq_timemgr_clock_glc' , &
       seq_timemgr_clock_wav  = 'seq_timemgr_clock_wav' , &
       seq_timemgr_clock_rof  = 'seq_timemgr_clock_rof' , &
       seq_timemgr_clock_esp  = 'seq_timemgr_clock_esp'
  character(len=8),private,parameter :: seq_timemgr_clocks(max_clocks) = &
       (/'drv     ','atm     ','lnd     ','ocn     ', &
       'ice     ','glc     ','wav     ','rof     ', &
       'iac     ','esp     '/)

  ! Alarms on both component clocks and driver clock
  integer(SHR_KIND_IN),private,parameter :: &
       seq_timemgr_nalarm_restart    = 1 , & ! driver and component clock alarm
       seq_timemgr_nalarm_run        = 2 , & ! driver and component clock alarm
       seq_timemgr_nalarm_stop       = 3 , & ! driver and component clock alarm
       seq_timemgr_nalarm_datestop   = 4 , & ! driver and component clock alarm
       seq_timemgr_nalarm_history    = 5 , & ! driver and component clock alarm
       seq_timemgr_nalarm_atmrun     = 6 , & ! driver only clock alarm
       seq_timemgr_nalarm_lndrun     = 7 , & ! driver only clock alarm
       seq_timemgr_nalarm_ocnrun     = 8 , & ! driver only clock alarm
       seq_timemgr_nalarm_icerun     = 9 , & ! driver only clock alarm
       seq_timemgr_nalarm_glcrun     =10 , & ! driver only clock alarm
       seq_timemgr_nalarm_glcrun_avg =11 , & ! driver only clock alarm
       seq_timemgr_nalarm_ocnnext    =12 , & ! driver only clock alarm
       seq_timemgr_nalarm_tprof      =13 , & ! driver and component clock alarm
       seq_timemgr_nalarm_histavg    =14 , & ! driver and component clock alarm
       seq_timemgr_nalarm_rofrun     =15 , & ! driver only clock alarm
       seq_timemgr_nalarm_wavrun     =16 , & ! driver only clock alarm
       seq_timemgr_nalarm_iacrun     =17 , & ! driver only clock alarm
       seq_timemgr_nalarm_esprun     =18 , & ! driver only clock alarm
       seq_timemgr_nalarm_pause      =19 , &
       seq_timemgr_nalarm_barrier    =20 , & ! driver and component clock alarm
       max_alarms = seq_timemgr_nalarm_barrier

  character(len=*),public,parameter :: &
       seq_timemgr_alarm_restart    = 'seq_timemgr_alarm_restart ', &
       seq_timemgr_alarm_run        = 'seq_timemgr_alarm_run     ', &
       seq_timemgr_alarm_stop       = 'seq_timemgr_alarm_stop    ', &
       seq_timemgr_alarm_datestop   = 'seq_timemgr_alarm_datestop', &
       seq_timemgr_alarm_history    = 'seq_timemgr_alarm_history ', &
       seq_timemgr_alarm_atmrun     = 'seq_timemgr_alarm_atmrun  ', &
       seq_timemgr_alarm_lndrun     = 'seq_timemgr_alarm_lndrun  ', &
       seq_timemgr_alarm_ocnrun     = 'seq_timemgr_alarm_ocnrun  ', &
       seq_timemgr_alarm_icerun     = 'seq_timemgr_alarm_icerun  ', &
       seq_timemgr_alarm_glcrun     = 'seq_timemgr_alarm_glcrun  ', &
       seq_timemgr_alarm_glcrun_avg = 'seq_timemgr_alarm_glcrun_avg' , &
       seq_timemgr_alarm_ocnnext    = 'seq_timemgr_alarm_ocnnext ', &
       seq_timemgr_alarm_tprof      = 'seq_timemgr_alarm_tprof   ', &
       seq_timemgr_alarm_histavg    = 'seq_timemgr_alarm_histavg ', &
       seq_timemgr_alarm_rofrun     = 'seq_timemgr_alarm_rofrun  ', &
       seq_timemgr_alarm_wavrun     = 'seq_timemgr_alarm_wavrun  ', &
       seq_timemgr_alarm_iacrun     = 'seq_timemgr_alarm_iacrun  ', &
       seq_timemgr_alarm_esprun     = 'seq_timemgr_alarm_esprun  ', &
       seq_timemgr_alarm_pause      = 'seq_timemgr_alarm_pause   ', &
       seq_timemgr_alarm_barrier    = 'seq_timemgr_alarm_barrier '

  ! Active pause - resume components
  logical, private :: pause_active(max_clocks) = .false.

  ! Active post-data assimilation components
  logical, private :: data_assimilation_active(max_clocks) = .false.

  type EClock_pointer     ! needed for array of pointers
     type(ESMF_Clock),pointer :: EClock => null()
  end type EClock_pointer

  type seq_timemgr_type
     private
     type(EClock_pointer) :: ECP(max_clocks)    ! ESMF clocks, array of pointers
     type(ESMF_Alarm) :: EAlarm(max_clocks,max_alarms) ! array of clock alarms
  end type seq_timemgr_type

  ! --- Private local data ----------------------------------------------------

  type(ESMF_Calendar), target, save :: seq_timemgr_cal      ! calendar
  character(SHR_KIND_CL)      ,save :: seq_timemgr_calendar ! calendar string
  integer, parameter                :: SecPerDay = 86400    ! Seconds per day

  integer :: seq_timemgr_pause_sig_index  ! Index of pause comp with smallest dt
  logical :: seq_timemgr_esp_run_on_pause ! Run ESP component on pause cycle
  logical :: seq_timemgr_end_restart      ! write restarts at end of run?

  !===============================================================================

contains

  !===============================================================================
  ! !IROUTINE: seq_timemgr_clockInit -- Initializes clocks
  !
  ! !DESCRIPTION:
  !
  !     Initializes clock
  !
  ! !INTERFACE: ------------------------------------------------------------------

  subroutine seq_timemgr_clockInit(SyncClock, nmlfile, restart, restart_file, pioid, mpicom, &
       EClock_drv, EClock_atm, EClock_lnd, EClock_ocn, EClock_ice, Eclock_glc, &
       Eclock_rof, EClock_wav, Eclock_esp, Eclock_iac)

    ! !USES:
    use pio, only : file_desc_T
    use shr_file_mod,   only : shr_file_getunit, shr_file_freeunit
    use shr_mpi_mod,    only : shr_mpi_bcast
    use seq_io_read_mod

    implicit none

    ! !INPUT/OUTPUT PARAMETERS:

    type(seq_timemgr_type),  intent(INOUT) :: SyncClock    ! sync clock
    character(len=*),        intent(IN)    :: nmlfile      ! namelist file
    integer,                 intent(IN)    :: mpicom       ! MPI communicator
    logical,                 intent(IN)    :: restart      ! restart logical
    character(len=*),        intent(IN)    :: restart_file
    type(ESMF_clock),target, intent(IN)    :: EClock_drv   ! drv clock
    type(ESMF_clock),target, intent(IN)    :: EClock_atm   ! atm clock
    type(ESMF_clock),target, intent(IN)    :: EClock_lnd   ! lnd clock
    type(ESMF_clock),target, intent(IN)    :: EClock_ocn   ! ocn clock
    type(ESMF_clock),target, intent(IN)    :: EClock_ice   ! ice clock
    type(ESMF_clock),target, intent(IN)    :: EClock_glc   ! glc clock
    type(ESMF_clock),target, intent(IN)    :: EClock_rof   ! rof clock
    type(ESMF_clock),target, intent(IN)    :: EClock_wav   ! wav clock
    type(ESMF_clock),target, intent(IN)    :: EClock_iac   ! iac clock
    type(ESMF_clock),target, intent(IN)    :: EClock_esp   ! esp clock
    type(file_desc_t)                      :: pioid

    !----- local -----
    character(len=*), parameter :: subname = '(seq_timemgr_clockInit) '
    type(ESMF_Time)             :: StartTime          ! Start time
    type(ESMF_Time)             :: RefTime            ! Reference time
    type(ESMF_Time)             :: CurrTime           ! Current time
    type(ESMF_Time)             :: OffsetTime         ! local computed time
    type(ESMF_Time)             :: StopTime1          ! Stop time
    type(ESMF_Time)             :: StopTime2          ! Stop time
    type(ESMF_Time)             :: StopTime, minStopTime ! Stop time
    type(ESMF_TimeInterval)     :: TimeStep           ! Clock time-step
    type(ESMF_TimeInterval)     :: cplTimeStep           ! Clock time-step
    type(ESMF_CalKind_Flag)     :: esmf_caltype       ! local esmf calendar
    integer                     :: rc                 ! Return code
    integer                     :: n, i               ! index
    integer                     :: min_dt             ! smallest time step
    integer                     :: dtime(max_clocks)  ! time-step to use
    integer                     :: offset(max_clocks) ! run offset
    integer                     :: unitn              ! i/o unit number
    integer                     :: iam                ! pe rank

    character(SHR_KIND_CS)  :: calendar              ! Calendar type
    character(SHR_KIND_CS)  :: stop_option           ! Stop option units
    integer(SHR_KIND_IN)    :: stop_n                ! Number until stop
    integer(SHR_KIND_IN)    :: stop_ymd              ! Stop date (YYYYMMDD)
    integer(SHR_KIND_IN)    :: stop_tod              ! Stop time-of-day
    character(SHR_KIND_CS)  :: restart_option        ! Restart option units
    integer(SHR_KIND_IN)    :: restart_n             ! Number until restart interval
    integer(SHR_KIND_IN)    :: restart_ymd           ! Restart date (YYYYMMDD)
    character(SHR_KIND_CS)  :: pause_option          ! Pause option units
    integer(SHR_KIND_IN)    :: pause_n               ! Number between pause intervals
    integer(SHR_KIND_IN)    :: RestInterval              ! Component Restart Interval
    integer(SHR_KIND_IN)    :: drvrestinterval        ! Driver Restart Interval

    logical :: pause_active_atm
    logical :: pause_active_cpl
    logical :: pause_active_ocn
    logical :: pause_active_wav
    logical :: pause_active_glc
    logical :: pause_active_ice
    logical :: pause_active_rof
    logical :: pause_active_lnd
    logical :: pause_active_iac

    logical :: data_assimilation_atm
    logical :: data_assimilation_cpl
    logical :: data_assimilation_ocn
    logical :: data_assimilation_wav
    logical :: data_assimilation_glc
    logical :: data_assimilation_ice
    logical :: data_assimilation_rof
    logical :: data_assimilation_lnd
    logical :: data_assimilation_iac

    character(SHR_KIND_CS)  :: history_option        ! History option units
    integer(SHR_KIND_IN)    :: history_n             ! Number until history interval
    integer(SHR_KIND_IN)    :: history_ymd           ! History date (YYYYMMDD)
    character(SHR_KIND_CS)  :: histavg_option        ! Histavg option units
    integer(SHR_KIND_IN)    :: histavg_n             ! Number until histavg interval
    integer(SHR_KIND_IN)    :: histavg_ymd           ! Histavg date (YYYYMMDD)
    character(SHR_KIND_CS)  :: barrier_option        ! Barrier option units
    integer(SHR_KIND_IN)    :: barrier_n             ! Number until barrier interval
    integer(SHR_KIND_IN)    :: barrier_ymd           ! Barrier date (YYYYMMDD)
    character(SHR_KIND_CS)  :: tprof_option          ! tprof option units
    integer(SHR_KIND_IN)    :: tprof_n               ! Number until tprof interval
    integer(SHR_KIND_IN)    :: tprof_ymd             ! tprof date (YYYYMMDD)
    integer(SHR_KIND_IN)    :: start_ymd             ! Start date ([YY]YYYYMMDD)
    integer(SHR_KIND_IN)    :: start_tod             ! Start time of day (seconds)
    integer(SHR_KIND_IN)    :: curr_ymd              ! Current ymd ([YY]YYYYMMDD)
    integer(SHR_KIND_IN)    :: curr_tod              ! Current tod (seconds)
    integer(SHR_KIND_IN)    :: ref_ymd               ! Reference date (YYYYMMDD)
    integer(SHR_KIND_IN)    :: ref_tod               ! Reference time of day (seconds)
    integer(SHR_KIND_IN)    :: atm_cpl_dt            ! Atmosphere coupling interval
    integer(SHR_KIND_IN)    :: lnd_cpl_dt            ! Land coupling interval
    integer(SHR_KIND_IN)    :: ice_cpl_dt            ! Sea-Ice coupling interval
    integer(SHR_KIND_IN)    :: ocn_cpl_dt            ! Ocean coupling interval
    integer(SHR_KIND_IN)    :: glc_cpl_dt            ! Glc coupling interval
    character(SHR_KIND_CS)  :: glc_avg_period        ! Glc avering coupling period
    integer(SHR_KIND_IN)    :: rof_cpl_dt            ! Runoff coupling interval
    integer(SHR_KIND_IN)    :: wav_cpl_dt            ! Wav coupling interval
    integer(SHR_KIND_IN)    :: iac_cpl_dt            ! Iac coupling interval
    integer(SHR_KIND_IN)    :: esp_cpl_dt            ! Esp coupling interval
    integer(SHR_KIND_IN)    :: atm_cpl_offset        ! Atmosphere coupling interval
    integer(SHR_KIND_IN)    :: lnd_cpl_offset        ! Land coupling interval
    integer(SHR_KIND_IN)    :: ice_cpl_offset        ! Sea-Ice coupling interval
    integer(SHR_KIND_IN)    :: ocn_cpl_offset        ! Ocean coupling interval
    integer(SHR_KIND_IN)    :: glc_cpl_offset        ! Glc coupling interval
    integer(SHR_KIND_IN)    :: wav_cpl_offset        ! Wav coupling interval
    integer(SHR_KIND_IN)    :: rof_cpl_offset        ! Runoff coupling interval
    integer(SHR_KIND_IN)    :: esp_cpl_offset        ! Esp coupling interval
    integer(SHR_KIND_IN)    :: iac_cpl_offset        ! Iac coupling interval
    logical                 :: esp_run_on_pause      ! Run ESP on pause cycle
    logical                 :: end_restart           ! Write restart at end of run
    integer(SHR_KIND_IN)    :: ierr                  ! Return code

    character(len=*), parameter ::  F0A = "(2A,A)"
    character(len=*), parameter ::  F0I = "(2A,I10)"
    character(len=*), parameter ::  F0L = "(2A,L3)"

    namelist /seq_timemgr_inparm/  calendar, curr_ymd, curr_tod,  &
         stop_option, stop_n, stop_ymd, stop_tod,                &
         restart_option, restart_n, restart_ymd,                 &
         pause_option,   &
         pause_n,           &
         pause_active_atm, &
         pause_active_cpl, &
         pause_active_ocn, &
         pause_active_wav, &
         pause_active_iac, &
         pause_active_glc, &
         pause_active_ice, &
         pause_active_rof, &
         pause_active_lnd, &
         data_assimilation_atm, &
         data_assimilation_cpl, &
         data_assimilation_ocn, &
         data_assimilation_wav, &
         data_assimilation_iac, &
         data_assimilation_glc, &
         data_assimilation_ice, &
         data_assimilation_rof, &
         data_assimilation_lnd, &
         history_option, history_n, history_ymd,                 &
         histavg_option, histavg_n, histavg_ymd,                 &
         barrier_option, barrier_n, barrier_ymd,                 &
         tprof_option, tprof_n, tprof_ymd,                       &
         start_ymd, start_tod, ref_ymd, ref_tod,                 &
         atm_cpl_dt, ocn_cpl_dt, ice_cpl_dt, lnd_cpl_dt,         &
         atm_cpl_offset, lnd_cpl_offset, ocn_cpl_offset,         &
         ice_cpl_offset, glc_cpl_dt, glc_cpl_offset, glc_avg_period, &
         wav_cpl_dt, wav_cpl_offset, esp_cpl_dt, esp_cpl_offset, &
         iac_cpl_dt, iac_cpl_offset,                             &
         rof_cpl_dt, rof_cpl_offset, esp_run_on_pause, end_restart
    !-------------------------------------------------------------------------------
    ! Notes:
    !-------------------------------------------------------------------------------

    SyncClock%ECP(seq_timemgr_nclock_drv)%EClock     => EClock_drv
    SyncClock%ECP(seq_timemgr_nclock_atm)%EClock     => EClock_atm
    SyncClock%ECP(seq_timemgr_nclock_lnd)%EClock     => EClock_lnd
    SyncClock%ECP(seq_timemgr_nclock_ocn)%EClock     => EClock_ocn
    SyncClock%ECP(seq_timemgr_nclock_ice)%EClock     => EClock_ice
    SyncClock%ECP(seq_timemgr_nclock_glc)%EClock     => EClock_glc
    SyncClock%ECP(seq_timemgr_nclock_rof)%EClock     => EClock_rof
    SyncClock%ECP(seq_timemgr_nclock_wav)%EClock     => EClock_wav
    SyncClock%ECP(seq_timemgr_nclock_esp)%EClock     => EClock_esp
    SyncClock%ECP(seq_timemgr_nclock_iac)%EClock     => EClock_iac

    call mpi_comm_rank(mpicom,iam,ierr)

    !---------------------------------------------------------------------------
    ! Set syncclock on root pe
    !---------------------------------------------------------------------------

    if (iam == 0) then

       !---------------------------------------------------------------------------
       ! Set namelist defaults
       !---------------------------------------------------------------------------
       calendar         = seq_timemgr_noleap
       stop_option      = ' '
       stop_n           = -1
       stop_ymd         = -1
       stop_tod         = 0
       restart_option   = seq_timemgr_optYearly
       restart_n        = -1
       restart_ymd      = -1
       pause_option     = seq_timemgr_optNever
       pause_n          = -1
       pause_active_atm = .false.
       pause_active_cpl = .false.
       pause_active_ocn = .false.
       pause_active_wav = .false.
       pause_active_glc = .false.
       pause_active_ice = .false.
       pause_active_rof = .false.
       pause_active_lnd = .false.
       pause_active_iac = .false.
       data_assimilation_atm = .false.
       data_assimilation_cpl = .false.
       data_assimilation_ocn = .false.
       data_assimilation_wav = .false.
       data_assimilation_glc = .false.
       data_assimilation_ice = .false.
       data_assimilation_rof = .false.
       data_assimilation_lnd = .false.
       data_assimilation_iac = .false.

       history_option   = seq_timemgr_optNever
       history_n        = -1
       history_ymd      = -1
       histavg_option   = seq_timemgr_optNever
       histavg_n        = -1
       histavg_ymd      = -1
       barrier_option   = seq_timemgr_optNever
       barrier_n        = -1
       barrier_ymd      = -1
       tprof_option     = seq_timemgr_optNever
       tprof_n          = -1
       tprof_ymd        = -1
       start_ymd        = 0
       start_tod        = 0
       ref_ymd          = 0
       ref_tod          = 0
       curr_ymd         = 0
       curr_tod         = 0
       atm_cpl_dt       = 0
       lnd_cpl_dt       = 0
       ice_cpl_dt       = 0
       ocn_cpl_dt       = 0
       glc_cpl_dt       = 0
       glc_avg_period   = seq_timemgr_optGLCCouplingPeriod
       rof_cpl_dt       = 0
       wav_cpl_dt       = 0
       esp_cpl_dt       = 0
       iac_cpl_dt       = 0
       atm_cpl_offset   = 0
       lnd_cpl_offset   = 0
       ice_cpl_offset   = 0
       ocn_cpl_offset   = 0
       glc_cpl_offset   = 0
       rof_cpl_offset   = 0
       wav_cpl_offset   = 0
       esp_cpl_offset   = 0
       iac_cpl_offset   = 0
       esp_run_on_pause = .true.
       end_restart      = .true.

       !---------------------------------------------------------------------------
       ! Read in namelist
       !---------------------------------------------------------------------------
       unitn = shr_file_getUnit()
       write(logunit,F0A) trim(subname),' Read in seq_timemgr_inparm namelist from: '//trim(nmlfile)
       open( unitn, file=trim(nmlfile), status='old' )
       ierr = 1
       do while( ierr /= 0 )
          read(unitn,nml=seq_timemgr_inparm,iostat=ierr)
          if (ierr < 0) then
             call shr_sys_abort( subname//':: namelist read returns an'// &
                  ' end of file or end of record condition' )
          end if
       end do
       close(unitn)
       call shr_file_freeUnit( unitn )
    endif

    !---------------------------------------------------------------------------
    ! Read Restart (seq_io is called on all CPLID pes)
    ! NOTE: slightly messy, seq_io is only valid on CPLID
    !---------------------------------------------------------------------------
    if (restart) then
       if (seq_comm_iamin(CPLID)) then
          call seq_io_read(restart_file,pioid,start_ymd,'seq_timemgr_start_ymd')
          call seq_io_read(restart_file,pioid,start_tod,'seq_timemgr_start_tod')
          call seq_io_read(restart_file,pioid,ref_ymd  ,'seq_timemgr_ref_ymd')
          call seq_io_read(restart_file,pioid,ref_tod  ,'seq_timemgr_ref_tod')
          call seq_io_read(restart_file,pioid,curr_ymd ,'seq_timemgr_curr_ymd')
          call seq_io_read(restart_file,pioid,curr_tod ,'seq_timemgr_curr_tod')
       endif
       !--- Send from CPLID ROOT to GLOBALID ROOT, use bcast as surrogate
       call shr_mpi_bcast(start_ymd,mpicom,pebcast=seq_comm_gloroot(CPLID))
       call shr_mpi_bcast(start_tod,mpicom,pebcast=seq_comm_gloroot(CPLID))
       call shr_mpi_bcast(  ref_ymd,mpicom,pebcast=seq_comm_gloroot(CPLID))
       call shr_mpi_bcast(  ref_tod,mpicom,pebcast=seq_comm_gloroot(CPLID))
       call shr_mpi_bcast( curr_ymd,mpicom,pebcast=seq_comm_gloroot(CPLID))
       call shr_mpi_bcast( curr_tod,mpicom,pebcast=seq_comm_gloroot(CPLID))
    endif

    if (iam == 0) then
       !---------------------------------------------------------------------------
       ! Modify namelist as needed
       !---------------------------------------------------------------------------

       if (lnd_cpl_dt == 0) lnd_cpl_dt = atm_cpl_dt ! Copy atm coupling time into lnd
       if (rof_cpl_dt == 0) rof_cpl_dt = atm_cpl_dt ! Copy atm coupling time into rof
       if (ice_cpl_dt == 0) ice_cpl_dt = atm_cpl_dt ! Copy atm coupling time into ice
       if (ocn_cpl_dt == 0) ocn_cpl_dt = atm_cpl_dt ! Copy atm coupling time into ocn
       if (glc_cpl_dt == 0) glc_cpl_dt = atm_cpl_dt ! Copy atm coupling time into glc
       if (wav_cpl_dt == 0) wav_cpl_dt = atm_cpl_dt ! Copy atm coupling time into wav
       if (esp_cpl_dt == 0) esp_cpl_dt = atm_cpl_dt ! Copy atm coupling time into esp
       if (iac_cpl_dt == 0) iac_cpl_dt = atm_cpl_dt ! Copy atm coupling time into iac

       if ( ref_ymd == 0 ) then
          ref_ymd = start_ymd
          ref_tod = start_tod
       endif

       if ( curr_ymd == 0 ) then
          curr_ymd = start_ymd
          curr_tod = start_tod
       endif

       if ( stop_ymd < 0) then
          ! If we want to go beyond this date we need date vars to be i8
          stop_ymd = 2147480101
          stop_tod = 0
       endif

       if (trim(restart_option) == trim(seq_timemgr_optNone) .or. &
            trim(restart_option) == trim(seq_timemgr_optNever)) then
          if (end_restart) then
             end_restart = .false.
             write(logunit,F0A) trim(subname),' WARNING: overriding end_restart to '// &
                  'false based on restart_option '
          endif
       endif

       if (trim(restart_option) == trim(seq_timemgr_optEnd)) then
          restart_option = seq_timemgr_optNone
          write(logunit,F0A) trim(subname),' WARNING: overriding restart_option to '// &
               'none and verifying end_restart flag is true '
          if (.not. end_restart) then
             end_restart = .true.
             write(logunit,F0A) trim(subname),' WARNING: overriding end_restart to '// &
                  'true based on restart_option (end) '
          endif
       endif

       !---------------------------------------------------------------------------
       ! Print out the namelist settings
       !---------------------------------------------------------------------------

       write(logunit,F0A) ' '
       write(logunit,F0A) trim(subname),' Clock Init Settings:'
       write(logunit,F0A) trim(subname),' calendar       = ',trim(calendar)
       write(logunit,F0A) trim(subname),' stop_option    = ',trim(stop_option)
       write(logunit,F0I) trim(subname),' stop_n         = ',stop_n
       write(logunit,F0I) trim(subname),' stop_ymd       = ',stop_ymd
       write(logunit,F0I) trim(subname),' stop_tod       = ',stop_tod
       write(logunit,F0A) trim(subname),' restart_option = ',trim(restart_option)
       write(logunit,F0I) trim(subname),' restart_n      = ',restart_n
       write(logunit,F0I) trim(subname),' restart_ymd    = ',restart_ymd
       write(logunit,F0L) trim(subname),' end_restart    = ',end_restart
       write(logunit,F0A) trim(subname),' pause_option   = ',&
            trim(pause_option)
       write(logunit,F0I) trim(subname),' pause_n        = ',&
            pause_n
       write(logunit,F0L) trim(subname),' esp_run_on_pause = ',esp_run_on_pause
       write(logunit,F0A) trim(subname),' history_option = ',trim(history_option)
       write(logunit,F0I) trim(subname),' history_n      = ',history_n
       write(logunit,F0I) trim(subname),' history_ymd    = ',history_ymd
       write(logunit,F0A) trim(subname),' histavg_option = ',trim(histavg_option)
       write(logunit,F0I) trim(subname),' histavg_n      = ',histavg_n
       write(logunit,F0I) trim(subname),' histavg_ymd    = ',histavg_ymd
       write(logunit,F0A) trim(subname),' barrier_option = ',trim(barrier_option)
       write(logunit,F0I) trim(subname),' barrier_n      = ',barrier_n
       write(logunit,F0I) trim(subname),' barrier_ymd    = ',barrier_ymd
       write(logunit,F0A) trim(subname),' tprof_option   = ',trim(tprof_option)
       write(logunit,F0I) trim(subname),' tprof_n        = ',tprof_n
       write(logunit,F0I) trim(subname),' tprof_ymd      = ',tprof_ymd
       write(logunit,F0I) trim(subname),' start_ymd      = ',start_ymd
       write(logunit,F0I) trim(subname),' start_tod      = ',start_tod
       write(logunit,F0I) trim(subname),' ref_ymd        = ',ref_ymd
       write(logunit,F0I) trim(subname),' ref_tod        = ',ref_tod
       write(logunit,F0I) trim(subname),' atm_cpl_dt     = ',atm_cpl_dt
       write(logunit,F0I) trim(subname),' lnd_cpl_dt     = ',lnd_cpl_dt
       write(logunit,F0I) trim(subname),' ice_cpl_dt     = ',ice_cpl_dt
       write(logunit,F0I) trim(subname),' ocn_cpl_dt     = ',ocn_cpl_dt
       write(logunit,F0I) trim(subname),' glc_cpl_dt     = ',glc_cpl_dt
       write(logunit,F0A) trim(subname),' glc_avg_period = ',glc_avg_period
       write(logunit,F0I) trim(subname),' rof_cpl_dt     = ',rof_cpl_dt
       write(logunit,F0I) trim(subname),' wav_cpl_dt     = ',wav_cpl_dt
       write(logunit,F0I) trim(subname),' esp_cpl_dt     = ',esp_cpl_dt
       write(logunit,F0I) trim(subname),' iac_cpl_dt     = ',iac_cpl_dt
       write(logunit,F0I) trim(subname),' atm_cpl_offset = ',atm_cpl_offset
       write(logunit,F0I) trim(subname),' lnd_cpl_offset = ',lnd_cpl_offset
       write(logunit,F0I) trim(subname),' ice_cpl_offset = ',ice_cpl_offset
       write(logunit,F0I) trim(subname),' ocn_cpl_offset = ',ocn_cpl_offset
       write(logunit,F0I) trim(subname),' glc_cpl_offset = ',glc_cpl_offset
       write(logunit,F0I) trim(subname),' rof_cpl_offset = ',rof_cpl_offset
       write(logunit,F0I) trim(subname),' wav_cpl_offset = ',wav_cpl_offset
       write(logunit,F0I) trim(subname),' esp_cpl_offset = ',esp_cpl_offset
       write(logunit,F0I) trim(subname),' iac_cpl_offset = ',iac_cpl_offset
       write(logunit,F0A) ' '

       !---------------------------------------------------------------------------
       ! Check a few things
       !---------------------------------------------------------------------------

       ! --- Coupling intervals ------------------------------------------------
       if ( atm_cpl_dt <= 0 .or. &
            lnd_cpl_dt /= atm_cpl_dt .or. &
            ice_cpl_dt /= atm_cpl_dt .or. &
            ocn_cpl_dt <= 0 .or. glc_cpl_dt <= 0 .or. rof_cpl_dt <=0 .or. &
            wav_cpl_dt <=0 .or. esp_cpl_dt <=0 .or. iac_cpl_dt <=0) then
          write(logunit,*) trim(subname),' ERROR: aliogrwe _cpl_dt = ', &
               atm_cpl_dt, lnd_cpl_dt, ice_cpl_dt, ocn_cpl_dt, glc_cpl_dt, &
               rof_cpl_dt, wav_cpl_dt, esp_cpl_dt, iac_cpl_dt
          call shr_sys_abort( subname//': ERROR coupling intervals invalid' )
       end if
       ! --- Coupling offsets --------------------------------------------------
       if ( abs(atm_cpl_offset) > atm_cpl_dt .or. &
            abs(lnd_cpl_offset) > lnd_cpl_dt .or. &
            abs(ice_cpl_offset) > ice_cpl_dt .or. &
            abs(glc_cpl_offset) > glc_cpl_dt .or. &
            abs(rof_cpl_offset) > rof_cpl_dt .or. &
            abs(wav_cpl_offset) > wav_cpl_dt .or. &
            abs(esp_cpl_offset) > esp_cpl_dt .or. &
            abs(iac_cpl_offset) > iac_cpl_dt .or. &
            abs(ocn_cpl_offset) > ocn_cpl_dt) then
          write(logunit,*) trim(subname),' ERROR: aliogrwe _cpl_offset = ', &
               atm_cpl_offset, lnd_cpl_offset, ice_cpl_offset, ocn_cpl_offset, &
               glc_cpl_offset, rof_cpl_offset, wav_cpl_offset, esp_cpl_offset, &
               iac_cpl_offset
          call shr_sys_abort( subname//': ERROR coupling offsets invalid' )
       end if

       ! --- Start time date ---------------------------------------------------
       ! If we want to go beyond this date we need date vars to be i8
       if ( (start_ymd < 101) .or. (start_ymd > 2147471231)) then
          write(logunit,*) subname,' ERROR: illegal start_ymd',start_ymd
          call shr_sys_abort( subname//': ERROR invalid start_ymd')
       end if

    endif

    !---------------------------------------------------------------------------
    ! Broadcast namelist data
    !---------------------------------------------------------------------------
    call shr_mpi_bcast( calendar,             mpicom )
    call shr_mpi_bcast( stop_n,               mpicom )
    call shr_mpi_bcast( stop_option,          mpicom )
    call shr_mpi_bcast( stop_ymd,             mpicom )
    call shr_mpi_bcast( stop_tod,             mpicom )
    call shr_mpi_bcast( restart_n,            mpicom )
    call shr_mpi_bcast( restart_option,       mpicom )
    call shr_mpi_bcast( restart_ymd,          mpicom )
    call shr_mpi_bcast( pause_n,              mpicom )
    call shr_mpi_bcast( pause_option,         mpicom )
    call shr_mpi_bcast(pause_active_atm,      mpicom )
    call shr_mpi_bcast(pause_active_cpl,      mpicom )
    call shr_mpi_bcast(pause_active_ocn,      mpicom )
    call shr_mpi_bcast(pause_active_wav,      mpicom )
    call shr_mpi_bcast(pause_active_glc,      mpicom )
    call shr_mpi_bcast(pause_active_ice,      mpicom )
    call shr_mpi_bcast(pause_active_rof,      mpicom )
    call shr_mpi_bcast(pause_active_lnd,      mpicom )
    call shr_mpi_bcast(pause_active_iac,      mpicom )
    call shr_mpi_bcast(data_assimilation_atm, mpicom )
    call shr_mpi_bcast(data_assimilation_cpl, mpicom )
    call shr_mpi_bcast(data_assimilation_ocn, mpicom )
    call shr_mpi_bcast(data_assimilation_wav, mpicom )
    call shr_mpi_bcast(data_assimilation_glc, mpicom )
    call shr_mpi_bcast(data_assimilation_ice, mpicom )
    call shr_mpi_bcast(data_assimilation_rof, mpicom )
    call shr_mpi_bcast(data_assimilation_lnd, mpicom )
    call shr_mpi_bcast(data_assimilation_iac, mpicom )

    call shr_mpi_bcast( history_n,            mpicom )
    call shr_mpi_bcast( history_option,       mpicom )
    call shr_mpi_bcast( history_ymd,          mpicom )
    call shr_mpi_bcast( histavg_n,            mpicom )
    call shr_mpi_bcast( histavg_option,       mpicom )
    call shr_mpi_bcast( histavg_ymd,          mpicom )
    call shr_mpi_bcast( tprof_n,              mpicom )
    call shr_mpi_bcast( barrier_n,            mpicom )
    call shr_mpi_bcast( barrier_option,       mpicom )
    call shr_mpi_bcast( barrier_ymd,          mpicom )
    call shr_mpi_bcast( tprof_option,         mpicom )
    call shr_mpi_bcast( tprof_ymd,            mpicom )
    call shr_mpi_bcast( start_ymd,            mpicom )
    call shr_mpi_bcast( start_tod,            mpicom )
    call shr_mpi_bcast( ref_ymd,              mpicom )
    call shr_mpi_bcast( ref_tod,              mpicom )
    call shr_mpi_bcast( curr_ymd,             mpicom )
    call shr_mpi_bcast( curr_tod,             mpicom )
    call shr_mpi_bcast( atm_cpl_dt,           mpicom )
    call shr_mpi_bcast( lnd_cpl_dt,           mpicom )
    call shr_mpi_bcast( ice_cpl_dt,           mpicom )
    call shr_mpi_bcast( ocn_cpl_dt,           mpicom )
    call shr_mpi_bcast( glc_cpl_dt,           mpicom )
    call shr_mpi_bcast( glc_avg_period,       mpicom )
    call shr_mpi_bcast( rof_cpl_dt,           mpicom )
    call shr_mpi_bcast( wav_cpl_dt,           mpicom )
    call shr_mpi_bcast( esp_cpl_dt,           mpicom )
    call shr_mpi_bcast( iac_cpl_dt,           mpicom )
    call shr_mpi_bcast( atm_cpl_offset,       mpicom )
    call shr_mpi_bcast( lnd_cpl_offset,       mpicom )
    call shr_mpi_bcast( ice_cpl_offset,       mpicom )
    call shr_mpi_bcast( ocn_cpl_offset,       mpicom )
    call shr_mpi_bcast( glc_cpl_offset,       mpicom )
    call shr_mpi_bcast( rof_cpl_offset,       mpicom )
    call shr_mpi_bcast( wav_cpl_offset,       mpicom )
    call shr_mpi_bcast( esp_cpl_offset,       mpicom )
    call shr_mpi_bcast( iac_cpl_offset,       mpicom )
    call shr_mpi_bcast( esp_run_on_pause,     mpicom )
    call shr_mpi_bcast( end_restart,          mpicom )

    ! --- derive a couple things ---
    if     (trim(histavg_option) == trim(seq_timemgr_optNever) .or. &
         trim(histavg_option) == trim(seq_timemgr_optNone)) then
       seq_timemgr_histavg_type = seq_timemgr_type_never
    elseif (trim(histavg_option) == trim(seq_timemgr_optNHours) .or. &
         trim(histavg_option) == trim(seq_timemgr_optNHour)) then
       seq_timemgr_histavg_type = seq_timemgr_type_nhour
    elseif (trim(histavg_option) == trim(seq_timemgr_optNDays) .or. &
         trim(histavg_option) == trim(seq_timemgr_optNDay)) then
       seq_timemgr_histavg_type = seq_timemgr_type_nday
    elseif (trim(histavg_option) == trim(seq_timemgr_optNMonths) .or. &
         trim(histavg_option) == trim(seq_timemgr_optNMonth)  .or. &
         trim(histavg_option) == trim(seq_timemgr_optMonthly)) then
       seq_timemgr_histavg_type = seq_timemgr_type_nmonth
    elseif (trim(histavg_option) == trim(seq_timemgr_optNYears) .or. &
         trim(histavg_option) == trim(seq_timemgr_optNYear)  .or. &
         trim(histavg_option) == trim(seq_timemgr_optYearly)) then
       seq_timemgr_histavg_type = seq_timemgr_type_nyear
    else
       seq_timemgr_histavg_type = seq_timemgr_type_other
    endif


    ! --- Initialize generic stuff ---
    seq_timemgr_calendar             = shr_cal_calendarName(calendar)
    seq_timemgr_esp_run_on_pause     = esp_run_on_pause
    seq_timemgr_end_restart          = end_restart
    rc = 1
    i = 1
    ! --- Figure out which components (if any) are doing pause this run
    pause_active(seq_timemgr_nclock_atm) = pause_active_atm
    pause_active(seq_timemgr_nclock_drv) = pause_active_cpl
    pause_active(seq_timemgr_nclock_ocn) = pause_active_ocn
    pause_active(seq_timemgr_nclock_wav) = pause_active_wav
    pause_active(seq_timemgr_nclock_glc) = pause_active_glc
    pause_active(seq_timemgr_nclock_ice) = pause_active_ice
    pause_active(seq_timemgr_nclock_rof) = pause_active_rof
    pause_active(seq_timemgr_nclock_lnd) = pause_active_lnd
    pause_active(seq_timemgr_nclock_iac) = pause_active_iac

    ! Figure out which compoments need to do post-data assimilation processing
    data_assimilation_active(seq_timemgr_nclock_atm) = data_assimilation_atm
    data_assimilation_active(seq_timemgr_nclock_drv) = data_assimilation_cpl
    data_assimilation_active(seq_timemgr_nclock_ocn) = data_assimilation_ocn
    data_assimilation_active(seq_timemgr_nclock_wav) = data_assimilation_wav
    data_assimilation_active(seq_timemgr_nclock_glc) = data_assimilation_glc
    data_assimilation_active(seq_timemgr_nclock_ice) = data_assimilation_ice
    data_assimilation_active(seq_timemgr_nclock_rof) = data_assimilation_rof
    data_assimilation_active(seq_timemgr_nclock_lnd) = data_assimilation_lnd
    data_assimilation_active(seq_timemgr_nclock_iac) = data_assimilation_iac

    if ( ANY(pause_active) .and.                                              &
         (trim(pause_option) /= seq_timemgr_optNONE)  .and.                   &
         (trim(pause_option) /= seq_timemgr_optNever)) then
       do n = 1, max_clocks
          if (pause_active(n) .and. (iam == 0)) then
             write(logunit, '(4a)') subname, ': Pause active for ',           &
                  trim(seq_timemgr_clocks(n)),' component'
          end if
       end do
    end if

    ! --- Create the new calendar if not already set ------
    if ( trim(seq_timemgr_calendar) == trim(seq_timemgr_noleap)) then
       esmf_caltype = ESMF_CALKIND_NOLEAP
    else if ( trim(seq_timemgr_calendar) == trim(seq_timemgr_gregorian)) then
       esmf_caltype = ESMF_CALKIND_GREGORIAN
    else
       write(logunit,*) subname//': unrecognized ESMF calendar specified: '// &
            trim(seq_timemgr_calendar)
       call shr_sys_abort( subname//'ERROR:: bad calendar for ESMF' )
    end if

    seq_timemgr_cal = ESMF_CalendarCreate( name='CIME_'//seq_timemgr_calendar, &
         calkindflag=esmf_caltype, rc=rc )
    call seq_timemgr_ESMFCodeCheck( rc, subname//': error return from ESMF_CalendarCreate' )

    ! --- Initialize start, ref, and current date ---

    call seq_timemgr_ETimeInit( StartTime, start_ymd, start_tod, "Start date" )
    call seq_timemgr_ETimeInit( RefTime  , ref_ymd  , ref_tod  , "Reference date" )
    call seq_timemgr_ETimeInit( CurrTime , curr_ymd , curr_tod , "Current date")

    ! --- Figure out what time-stepping interval should be. ---------------

    dtime = 0
    dtime(seq_timemgr_nclock_atm     ) = atm_cpl_dt
    dtime(seq_timemgr_nclock_lnd     ) = lnd_cpl_dt
    dtime(seq_timemgr_nclock_ocn     ) = ocn_cpl_dt
    dtime(seq_timemgr_nclock_ice     ) = ice_cpl_dt
    dtime(seq_timemgr_nclock_glc     ) = glc_cpl_dt
    dtime(seq_timemgr_nclock_rof     ) = rof_cpl_dt
    dtime(seq_timemgr_nclock_wav     ) = wav_cpl_dt
    dtime(seq_timemgr_nclock_esp     ) = esp_cpl_dt
    dtime(seq_timemgr_nclock_iac     ) = iac_cpl_dt

    ! --- this finds the min of dtime excluding the driver value ---
    dtime(seq_timemgr_nclock_drv) = maxval(dtime)
    dtime(seq_timemgr_nclock_drv) = minval(dtime)

    ! --- For figuring pause cycle
    min_dt = maxval(dtime)
    seq_timemgr_pause_sig_index = -1

    do n = 1,max_clocks
       if ( mod(dtime(n),dtime(seq_timemgr_nclock_drv)) /= 0) then
          write(logunit,*) trim(subname),' ERROR: dtime inconsistent = ',dtime
          call shr_sys_abort( subname//' :coupling intervals not compatible' )
       endif
       if (pause_active(n) .and. (dtime(n) <= min_dt)) then
          min_dt = dtime(n)
          seq_timemgr_pause_sig_index = n
       end if
    enddo
    if (ANY(pause_active)) then
       if (seq_timemgr_pause_sig_index < 1) then
          write(logunit, *) subname,"ERROR: No pause_sig_index even with active pause"
          call shr_sys_abort(subname//"ERROR: No pause_sig_index even with active pause")
       end if
    else
       ! Don't try to run ESP on non-existent pauses
       seq_timemgr_esp_run_on_pause = .false.
    end if

    ! --- Initialize component and driver clocks and alarms common to components and driver clocks ---
    call ESMF_TimeIntervalSet( CplTimeStep, s=dtime(seq_timemgr_nclock_drv), rc=rc )
    do n = 1,max_clocks
       call ESMF_TimeIntervalSet( TimeStep, s=dtime(n), rc=rc )

       call seq_timemgr_ESMFCodeCheck( rc, subname//': error ESMF_TimeIntervalSet' )

       call seq_timemgr_EClockInit( TimeStep, StartTime, RefTime, CurrTime, SyncClock%ECP(n)%EClock)

       call seq_timemgr_alarmInit(SyncClock%ECP(n)%EClock, &
            EAlarm  = SyncClock%EAlarm(n,seq_timemgr_nalarm_run),  &
            option  = seq_timemgr_optNSeconds, &
            opt_n   = dtime(n),                &
            RefTime = CurrTime,                &
            alarmname = trim(seq_timemgr_alarm_run))

       call seq_timemgr_alarmInit(SyncClock%ECP(n)%EClock, &
            EAlarm  = SyncClock%EAlarm(n,seq_timemgr_nalarm_stop),  &
            option  = stop_option,         &
            opt_n   = stop_n,              &
            opt_ymd = stop_ymd,            &
            opt_tod = stop_tod,            &
            RefTime = CurrTime,            &
            cplTimeStep = cplTimeStep, &
            alarmname = trim(seq_timemgr_alarm_stop))

       call seq_timemgr_alarmInit(SyncClock%ECP(n)%EClock, &
            EAlarm  = SyncClock%EAlarm(n,seq_timemgr_nalarm_datestop),  &
            option  = seq_timemgr_optDate, &
            opt_ymd = stop_ymd,            &
            opt_tod = stop_tod,            &
            RefTime = StartTime,           &
            alarmname = trim(seq_timemgr_alarm_datestop))

       call seq_timemgr_alarmInit(SyncClock%ECP(n)%EClock, &
            EAlarm  = SyncClock%EAlarm(n,seq_timemgr_nalarm_restart),  &
            option  = restart_option,      &
            opt_n   = restart_n,           &
            opt_ymd = restart_ymd,         &
            RefTime = CurrTime,            &
            cplTimeStep = cplTimeStep, &
            alarmname = trim(seq_timemgr_alarm_restart))

       call seq_timemgr_alarmInit(SyncClock%ECP(n)%EClock, &
            EAlarm  = SyncClock%EAlarm(n,seq_timemgr_nalarm_history),  &
            option  = history_option,      &
            opt_n   = history_n,           &
            opt_ymd = history_ymd,         &
            RefTime = StartTime,           &
            cplTimeStep = cplTimeStep, &
            alarmname = trim(seq_timemgr_alarm_history))

       call seq_timemgr_alarmInit(SyncClock%ECP(n)%EClock, &
            EAlarm  = SyncClock%EAlarm(n,seq_timemgr_nalarm_histavg),  &
            option  = histavg_option,      &
            opt_n   = histavg_n,           &
            opt_ymd = histavg_ymd,         &
            RefTime = StartTime,           &
            cplTimeStep = cplTimeStep, &
            alarmname = trim(seq_timemgr_alarm_histavg))

       call seq_timemgr_alarmInit(SyncClock%ECP(n)%EClock, &
            EAlarm  = SyncClock%EAlarm(n,seq_timemgr_nalarm_barrier),  &
            option  = barrier_option,      &
            opt_n   = barrier_n,           &
            opt_ymd = barrier_ymd,         &
            RefTime = CurrTime,            &
            cplTimeStep = cplTimeStep, &
            alarmname = trim(seq_timemgr_alarm_barrier))

       call seq_timemgr_alarmInit(SyncClock%ECP(n)%EClock, &
            EAlarm  = SyncClock%EAlarm(n,seq_timemgr_nalarm_tprof),  &
            option  = tprof_option,        &
            opt_n   = tprof_n,             &
            opt_ymd = tprof_ymd,           &
            RefTime = StartTime,           &
            cplTimeStep = cplTimeStep, &
            alarmname = trim(seq_timemgr_alarm_tprof))

       call ESMF_AlarmGet(SyncClock%EAlarm(n,seq_timemgr_nalarm_stop), RingTime=StopTime1, rc=rc )
       call ESMF_AlarmGet(SyncClock%EAlarm(n,seq_timemgr_nalarm_datestop), RingTime=StopTime2, rc=rc )

       if (StopTime2 < StopTime1) then
          StopTime = StopTime2
       else
          StopTime = StopTime1
       endif
       if (n == 1) then
          minStopTIme = StopTime
       elseif (StopTime < minStopTime) then
          minStopTime = StopTime
       endif
       call ESMF_ClockSet(SyncClock%ECP(n)%EClock, StopTime=StopTime)

       ! Set the pause option if pause/resume is active
       if (pause_active(n)) then
          call seq_timemgr_alarmInit(SyncClock%ECP(n)%EClock,                  &
               EAlarm  = SyncClock%EAlarm(n,seq_timemgr_nalarm_pause),         &
               option  = pause_option,                                         &
               opt_n   = pause_n,                                              &
               RefTime = CurrTime,                                             &
               alarmname = trim(seq_timemgr_alarm_pause))
       else
          call seq_timemgr_alarmInit(SyncClock%ECP(n)%EClock,                  &
               EAlarm  = SyncClock%EAlarm(n,seq_timemgr_nalarm_pause),         &
               option  = seq_timemgr_optNever,                                 &
               opt_n   = -1,                                                   &
               RefTime = StartTime,                                            &
               alarmname = trim(seq_timemgr_alarm_pause))
       endif

    enddo

    ! --------------------------------------------------------------------
    ! Set the timing run alarms, these alarms are synced to the driver
    ! clock and determine when the component clocks are advanced.
    ! We need an offset here of the driver timestep because of the
    ! implementation.  We are advancing the clock first and we want
    ! components to run as soon as possible.  Without the driver offset
    ! the alarms would go off at the last possible timestep, not first.
    ! In addition, we allow the user to set other offsets if desired
    ! via namelist.  tcraig, 10/2007
    ! --------------------------------------------------------------------

    offset(seq_timemgr_nclock_drv)     = 0
    offset(seq_timemgr_nclock_atm)     = atm_cpl_offset
    offset(seq_timemgr_nclock_lnd)     = lnd_cpl_offset
    offset(seq_timemgr_nclock_ocn)     = ocn_cpl_offset
    offset(seq_timemgr_nclock_ice)     = ice_cpl_offset
    offset(seq_timemgr_nclock_glc)     = glc_cpl_offset
    offset(seq_timemgr_nclock_rof)     = rof_cpl_offset
    offset(seq_timemgr_nclock_wav)     = wav_cpl_offset
    offset(seq_timemgr_nclock_esp)     = esp_cpl_offset
    offset(seq_timemgr_nclock_iac)     = iac_cpl_offset

    call seq_timemgr_alarmGet(SyncClock%EAlarm(seq_timemgr_nclock_drv, &
         seq_timemgr_nalarm_restart), IntSec=drvRestInterval)

    do n = 1,max_clocks
       if (abs(offset(n)) > dtime(n)) then
          write(logunit,*) subname,' ERROR: offset too large',n,dtime(n),offset(n)
          call shr_sys_abort()
       endif

       !--- this is the required driver timestep offset ---
       offset(n) = offset(n) + dtime(seq_timemgr_nclock_drv)

       if (mod(offset(n),dtime(seq_timemgr_nclock_drv)) /= 0) then
          write(logunit,*) subname,' ERROR: offset not multiple',n,dtime(seq_timemgr_nclock_drv),offset(n)
          call shr_sys_abort()
       endif
       call ESMF_TimeIntervalSet( TimeStep, s=dtime(n), rc=rc )
       if(CurrTime + TimeStep > minStopTime .and. seq_comm_iamroot(CPLID)) then
          write(logunit,*) subname//" WARNING: Stop time too short, not all components will be advanced &
                                    &and restarts won't be written"
       endif
       if (n /= seq_timemgr_nclock_esp .and. trim(restart_option) .ne. &
            trim(seq_timemgr_optNone) .and. &
            trim(restart_option) .ne. trim(seq_timemgr_optNever)) then
             call seq_timemgr_alarmGet(SyncClock%EAlarm(n,seq_timemgr_nalarm_restart), IntSec=RestInterval)
             if (RestInterval .ne. drvRestInterval) then
                write(logunit,*) subname, 'RestInterval=',RestInterval,&
                     ' drvrestinterval=',drvrestinterval
                call shr_sys_abort(trim(subname)//"Component RestInterval inconsistant with driver")
             endif
       endif
    enddo

    ! Set component run alarms on driver clock

    call ESMF_TimeIntervalSet( TimeStep, s=offset(seq_timemgr_nclock_atm), rc=rc )
    OffsetTime = CurrTime + TimeStep
    call seq_timemgr_alarmInit(SyncClock%ECP(seq_timemgr_nclock_drv)%EClock, &
         EAlarm  = SyncClock%EAlarm(seq_timemgr_nclock_drv,seq_timemgr_nalarm_atmrun),  &
         option  = seq_timemgr_optNSeconds,       &
         opt_n   = dtime(seq_timemgr_nclock_atm), &
         RefTime = OffsetTime,                    &
         alarmname = trim(seq_timemgr_alarm_atmrun))

    call ESMF_TimeIntervalSet( TimeStep, s=offset(seq_timemgr_nclock_lnd), rc=rc )
    OffsetTime = CurrTime + TimeStep
    call seq_timemgr_alarmInit(SyncClock%ECP(seq_timemgr_nclock_drv)%EClock, &
         EAlarm  = SyncClock%EAlarm(seq_timemgr_nclock_drv,seq_timemgr_nalarm_lndrun),  &
         option  = seq_timemgr_optNSeconds,       &
         opt_n   = dtime(seq_timemgr_nclock_lnd), &
         RefTime = OffsetTime,                    &
         alarmname = trim(seq_timemgr_alarm_lndrun))

    call ESMF_TimeIntervalSet( TimeStep, s=offset(seq_timemgr_nclock_rof), rc=rc )
    OffsetTime = CurrTime + TimeStep
    call seq_timemgr_alarmInit(SyncClock%ECP(seq_timemgr_nclock_drv)%EClock, &
         EAlarm  = SyncClock%EAlarm(seq_timemgr_nclock_drv,seq_timemgr_nalarm_rofrun),  &
         option  = seq_timemgr_optNSeconds,       &
         opt_n   = dtime(seq_timemgr_nclock_rof), &
         RefTime = OffsetTime,                    &
         alarmname = trim(seq_timemgr_alarm_rofrun))

    call ESMF_TimeIntervalSet( TimeStep, s=offset(seq_timemgr_nclock_ice), rc=rc )
    OffsetTime = CurrTime + TimeStep
    call seq_timemgr_alarmInit(SyncClock%ECP(seq_timemgr_nclock_drv)%EClock, &
         EAlarm  = SyncClock%EAlarm(seq_timemgr_nclock_drv,seq_timemgr_nalarm_icerun),  &
         option  = seq_timemgr_optNSeconds,       &
         opt_n   = dtime(seq_timemgr_nclock_ice), &
         RefTime = OffsetTime,                    &
         alarmname = trim(seq_timemgr_alarm_icerun))

    call ESMF_TimeIntervalSet( TimeStep, s=offset(seq_timemgr_nclock_wav), rc=rc )
    OffsetTime = CurrTime + TimeStep
    call seq_timemgr_alarmInit(SyncClock%ECP(seq_timemgr_nclock_drv)%EClock, &
         EAlarm  = SyncClock%EAlarm(seq_timemgr_nclock_drv,seq_timemgr_nalarm_wavrun),  &
         option  = seq_timemgr_optNSeconds,       &
         opt_n   = dtime(seq_timemgr_nclock_wav), &
         RefTime = OffsetTime,                    &
         alarmname = trim(seq_timemgr_alarm_wavrun))

    call ESMF_TimeIntervalSet( TimeStep, s=offset(seq_timemgr_nclock_iac), rc=rc )
    OffsetTime = CurrTime + TimeStep
    call seq_timemgr_alarmInit(SyncClock%ECP(seq_timemgr_nclock_drv)%EClock, &
       EAlarm  = SyncClock%EAlarm(seq_timemgr_nclock_drv,seq_timemgr_nalarm_iacrun),  &
       option  = seq_timemgr_optNSeconds,       &
       opt_n   = dtime(seq_timemgr_nclock_iac), &
       RefTime = OffsetTime,                    &
       alarmname = trim(seq_timemgr_alarm_iacrun))

    call ESMF_TimeIntervalSet( TimeStep, s=offset(seq_timemgr_nclock_glc), rc=rc )
    OffsetTime = CurrTime + TimeStep
    call ESMF_TimeIntervalSet( TimeStep, s=-offset(seq_timemgr_nclock_drv), rc=rc )
    OffsetTime = OffsetTime + TimeStep
    call seq_timemgr_alarmInit(SyncClock%ECP(seq_timemgr_nclock_drv)%EClock, &
         EAlarm  = SyncClock%EAlarm(seq_timemgr_nclock_drv,seq_timemgr_nalarm_glcrun),  &
         option  = seq_timemgr_optNSeconds,       &
         opt_n   = dtime(seq_timemgr_nclock_glc), &
         RefTime = OffsetTime,                    &
         alarmname = trim(seq_timemgr_alarm_glcrun))
    if (glc_avg_period == seq_timemgr_optGLCCouplingPeriod) then
       ! Create this alarm identically to the glcrun alarm (which is created above)
       call seq_timemgr_alarmInit(SyncClock%ECP(seq_timemgr_nclock_drv)%EClock, &
            EAlarm  = SyncClock%EAlarm(seq_timemgr_nclock_drv,seq_timemgr_nalarm_glcrun_avg),  &
            option  = seq_timemgr_optNSeconds,       &
            opt_n   = dtime(seq_timemgr_nclock_glc), &
            RefTime = OffsetTime,                    &
            alarmname = trim(seq_timemgr_alarm_glcrun_avg))
    else if (glc_avg_period == seq_timemgr_optYearly) then
       call seq_timemgr_alarmInit(SyncClock%ECP(seq_timemgr_nclock_drv)%EClock, &
            EAlarm  = SyncClock%EAlarm(seq_timemgr_nclock_drv,seq_timemgr_nalarm_glcrun_avg),  &
            option  = seq_timemgr_optYearly,         &
            RefTime = OffsetTime,                    &
            alarmname = trim(seq_timemgr_alarm_glcrun_avg))
    else
       call shr_sys_abort(subname//':: glc_avg_period can only be glc_coupling_period or yearly')
    end if

    call ESMF_TimeIntervalSet( TimeStep, s=offset(seq_timemgr_nclock_ocn), rc=rc )
    OffsetTime = CurrTime + TimeStep
    call seq_timemgr_alarmInit(SyncClock%ECP(seq_timemgr_nclock_drv)%EClock, &
         EAlarm  = SyncClock%EAlarm(seq_timemgr_nclock_drv,seq_timemgr_nalarm_ocnrun),  &
         option  = seq_timemgr_optNSeconds,       &
         opt_n   = dtime(seq_timemgr_nclock_ocn), &
         RefTime = OffsetTime,                    &
         alarmname = trim(seq_timemgr_alarm_ocnrun))

    ! --- this is the ocnrun alarm (there ^) offset by a -dtime of the driver
    call ESMF_TimeIntervalSet( TimeStep, s=offset(seq_timemgr_nclock_ocn), rc=rc )
    OffsetTime = CurrTime + TimeStep
    call ESMF_TimeIntervalSet( TimeStep, s=-offset(seq_timemgr_nclock_drv), rc=rc )
    OffsetTime = OffsetTime + TimeStep
    call seq_timemgr_alarmInit(SyncClock%ECP(seq_timemgr_nclock_drv)%EClock, &
         EAlarm  = SyncClock%EAlarm(seq_timemgr_nclock_drv,seq_timemgr_nalarm_ocnnext),  &
         option  = seq_timemgr_optNSeconds,       &
         opt_n   = dtime(seq_timemgr_nclock_ocn), &
         RefTime = OffsetTime,                    &
         alarmname = trim(seq_timemgr_alarm_ocnnext))

    call ESMF_TimeIntervalSet( TimeStep, s=offset(seq_timemgr_nclock_esp), rc=rc )
    OffsetTime = CurrTime + TimeStep
    call seq_timemgr_alarmInit(SyncClock%ECP(seq_timemgr_nclock_drv)%EClock, &
         EAlarm  = SyncClock%EAlarm(seq_timemgr_nclock_drv,seq_timemgr_nalarm_esprun),  &
         option  = seq_timemgr_optNSeconds,       &
         opt_n   = dtime(seq_timemgr_nclock_esp), &
         RefTime = OffsetTime,                    &
         alarmname = trim(seq_timemgr_alarm_esprun))

  end subroutine seq_timemgr_clockInit

  !===============================================================================
  !===============================================================================
  ! !IROUTINE: seq_timemgr_EClockGetData -- Get information from the clock
  !
  ! !DESCRIPTION:
  !
  !     Get various values from the clock.
  !
  ! !INTERFACE: ------------------------------------------------------------------

  subroutine seq_timemgr_EClockGetData( EClock, curr_yr, curr_mon, curr_day,    &
       curr_ymd, curr_tod, prev_ymd, prev_tod, start_ymd,     &
       start_tod, StepNo, ref_ymd, ref_tod,         &
       stop_ymd, stop_tod, dtime, ECurrTime, alarmcount,      &
       curr_cday, next_cday, curr_time, prev_time, calendar)

    implicit none

    ! !INPUT/OUTPUT PARAMETERS:

    type(ESMF_Clock),     intent(IN)            :: EClock     ! Input clock object
    integer(SHR_KIND_IN), intent(OUT), optional :: curr_yr    ! Current year
    integer(SHR_KIND_IN), intent(OUT), optional :: curr_mon   ! Current month
    integer(SHR_KIND_IN), intent(OUT), optional :: curr_day   ! Current day in month
    integer(SHR_KIND_IN), intent(OUT), optional :: curr_ymd   ! Current date YYYYMMDD
    integer(SHR_KIND_IN), intent(OUT), optional :: curr_tod   ! Current time of day (s)
    integer(SHR_KIND_IN), intent(OUT), optional :: prev_ymd   ! Previous date YYYYMMDD
    integer(SHR_KIND_IN), intent(OUT), optional :: prev_tod   ! Previous time of day (s)
    integer(SHR_KIND_IN), intent(OUT), optional :: start_ymd  ! Starting date YYYYMMDD
    integer(SHR_KIND_IN), intent(OUT), optional :: start_tod  ! Starting time-of-day (s)
    integer(SHR_KIND_IN), intent(OUT), optional :: StepNo     ! Number of steps taken
    integer(SHR_KIND_IN), intent(OUT), optional :: ref_ymd    ! Reference date YYYYMMDD
    integer(SHR_KIND_IN), intent(OUT), optional :: ref_tod    ! Reference time-of-day (s)
    integer(SHR_KIND_IN), intent(OUT), optional :: stop_ymd   ! Stop date YYYYMMDD
    integer(SHR_KIND_IN), intent(OUT), optional :: stop_tod   ! Stop time-of-day (s)
    integer(SHR_KIND_IN), intent(OUT), optional :: dtime      ! Time-step (seconds)
    integer(SHR_KIND_IN), intent(OUT), optional :: alarmcount ! Number of Valid Alarms
    type(ESMF_Time),      intent(OUT), optional :: ECurrTime  ! Current ESMF time
    real(SHR_KIND_R8)   , intent(OUT), optional :: curr_cday  ! current calendar day
    real(SHR_KIND_R8)   , intent(OUT), optional :: next_cday  ! current calendar day
    real(SHR_KIND_R8)   , intent(OUT), optional :: curr_time  ! time interval between current time
    ! and reference date
    real(SHR_KIND_R8)   , intent(OUT), optional :: prev_time  ! time interval between previous time
    ! and reference date
    character(len=*)    , intent(OUT), optional :: calendar   ! calendar type

    !----- local -----
    character(len=*), parameter :: subname = '(seq_timemgr_EClockGetData) '
    type(ESMF_Time) :: CurrentTime            ! Current time
    type(ESMF_Time) :: PreviousTime           ! Previous time
    type(ESMF_Time) :: StartTime              ! Start time
    type(ESMF_Time) :: StopTime               ! Stop time
    type(ESMF_Time) :: RefTime                ! Ref time
    type(ESMF_TimeInterval) :: timeStep       ! Clock, time-step
    type(ESMF_TimeInterval) :: timediff       ! Used to calculate curr_time
    integer(SHR_KIND_IN) :: rc                ! Return code
    integer(SHR_KIND_I8) :: advSteps          ! Number of time-steps that have advanced
    integer(SHR_KIND_IN) :: yy, mm, dd, sec   ! Return time values
    integer(SHR_KIND_IN) :: ymd               ! Date (YYYYMMDD)
    integer(SHR_KIND_IN) :: tod               ! time of day (sec)
    integer(SHR_KIND_IN) :: ldtime            ! local dtime
    integer(SHR_KIND_IN) :: days              ! number of whole days in time interval
    integer(SHR_KIND_IN) :: seconds           ! number of seconds in time interval
    integer(SHR_KIND_IN) :: acount            ! number of valid alarms
    real(SHR_KIND_R8) :: doy, tmpdoy          ! day of year
    real(SHR_KIND_R8),parameter :: c1 = 1.0_SHR_KIND_R8

    type(ESMF_Time) :: tmpTime                ! tmp time, needed for next_cday
    type(ESMF_TimeInterval) :: tmpDTime       ! tmp time interval, needed for next_cday

    !-------------------------------------------------------------------------------
    ! Notes:
    !-------------------------------------------------------------------------------
    if (present(calendar)) calendar = trim(seq_timemgr_calendar)

    call ESMF_ClockGet( EClock, currTime=CurrentTime, &
         advanceCount=advSteps, prevTime=previousTime, TimeStep=timeStep, &
         startTime=StartTime, stopTime=stopTime, refTime=RefTime, &
         AlarmCount=acount, rc=rc )
    call seq_timemgr_ESMFCodeCheck( rc, msg=subname//"Error from ESMF_ClockGet" )

    call ESMF_TimeGet( CurrentTime, yy=yy, mm=mm, dd=dd, s=sec, dayofyear_r8=doy, rc=rc )
    call seq_timemgr_ESMFCodeCheck( rc, msg=subname//"Error from ESMF_TimeGet" )
    call seq_timemgr_ETimeGet( CurrentTime, ymd=ymd, tod=tod )
    call ESMF_TimeIntervalGet( timeStep, s=ldtime, rc=rc )
    call seq_timemgr_ESMFCodeCheck( rc, msg=subname//"Error from ESMF_TimeIntervalGet" )

    if ( present(curr_yr)  ) curr_yr  = yy
    if ( present(curr_mon) ) curr_mon = mm
    if ( present(curr_day) ) curr_day = dd
    if ( present(curr_tod) ) curr_tod = tod
    if ( present(curr_ymd) ) curr_ymd = ymd
    if ( present(ECurrTime)) ECurrTime= CurrentTime
    if ( present(StepNo)   ) StepNo   = advSteps
    if ( present(dtime)    ) dtime    = ldtime
    if ( present(curr_cday)) curr_cday = doy
    if ( present(alarmcount)) alarmcount = acount
    if ( present(next_cday)) then
       call ESMF_TimeSet(tmpTime, yy=yy, mm=mm, dd=dd, s=tod, calendar=seq_timemgr_cal, rc=rc )
       call seq_timemgr_ESMFCodeCheck( rc, msg=subname//"Error from TimeSet tmpTime")
       call ESMF_TimeIntervalSet( tmpDTime, d=1, rc=rc )
       call seq_timemgr_ESMFCodeCheck( rc, msg=subname//"Error from TimeIntSet tmpDTime")
       tmpTime = tmpTime + tmpDTime
       call ESMF_TimeGet(tmpTime, dayOfYear_r8=tmpdoy, rc=rc)
       call seq_timemgr_ESMFCodeCheck( rc, msg=subname//"Error from TimeGet tmpdoy")
       next_cday = tmpdoy
    endif

    ! ---Current Time (the time interval between the current date and the reference date) ---
    if ( present(curr_time)) then
       timediff = CurrentTime - RefTime
       call ESMF_TimeIntervalGet(timediff, d=days, s=seconds, rc=rc)
       call seq_timemgr_ESMFCodeCheck( rc, msg=subname//"Error from  TimeIntervalGet timediff")
       curr_time = days + seconds/real(SecPerDay,SHR_KIND_R8)
    end if

    ! ---Previous Time (the time interval between the previous date and the reference date) ---
    if ( present(prev_time)) then
       timediff = PreviousTime - RefTime
       call ESMF_TimeIntervalGet(timediff, d=days, s=seconds, rc=rc)
       call seq_timemgr_ESMFCodeCheck( rc, msg=subname//"Error from  TimeIntervalGet timediff")
       prev_time = days + seconds/real(SecPerDay,SHR_KIND_R8)
    end if

    ! --- Previous time --------------------------------------------------------
    if ( present(prev_ymd) .or. present(prev_tod) )then
       call seq_timemgr_ETimeGet( PreviousTime, ymd=ymd, tod=tod )
       if ( present(prev_ymd) ) prev_ymd = ymd
       if ( present(prev_tod) ) prev_tod = tod
    end if

    ! --- If want start date -----------------------------------------------
    if ( present(start_ymd) .or. present(start_tod) )then
       call seq_timemgr_ETimeGet( StartTime, ymd=ymd, tod=tod )
       if ( present(start_ymd) ) start_ymd = ymd
       if ( present(start_tod) ) start_tod = tod
    end if

    ! --- If want stop date -----------------------------------------------
    if ( present(stop_ymd) .or. present(stop_tod) )then
       call seq_timemgr_ETimeGet( stopTime, ymd=ymd, tod=tod )
       if ( present(stop_ymd) ) stop_ymd = ymd
       if ( present(stop_tod) ) stop_tod = tod
    end if

    ! --- If want ref date -----------------------------------------------
    if ( present(ref_ymd) .or. present(ref_tod) )then
       call seq_timemgr_ETimeGet( RefTime, ymd=ymd, tod=tod )
       if ( present(ref_ymd) ) ref_ymd = ymd
       if ( present(ref_tod) ) ref_tod = tod
    end if

  end subroutine seq_timemgr_EClockGetData
  !===============================================================================
  !===============================================================================
  ! !IROUTINE: seq_timemgr_clockAdvance  -- Advance the syncclock
  !
  ! !DESCRIPTION:
  !
  ! Advance this clock
  !
  ! !INTERFACE: ------------------------------------------------------------------

  subroutine seq_timemgr_clockAdvance( SyncClock, force_stop, force_stop_ymd, force_stop_tod )

    implicit none

    ! !INPUT/OUTPUT PARAMETERS:

    type(seq_timemgr_type), intent(INOUT) :: SyncClock    ! Advancing clock
    logical, optional, intent(in) :: force_stop           ! force stop
    integer, optional, intent(in) :: force_stop_ymd       ! force stop ymd
    integer, optional, intent(in) :: force_stop_tod       ! force stop tod

    !----- local -----
    character(len=*), parameter :: subname = '(seq_timemgr_clockAdvance) '
    integer :: n
    type(ESMF_Time) :: NextAlarm              ! Next restart alarm time
    integer :: rc    ! Return code

    !-------------------------------------------------------------------------------
    ! Notes:
    !-------------------------------------------------------------------------------

    ! --- set datestop alarm to force_stop alarm ---

    do n = 1,max_clocks
       call seq_timemgr_alarmSetOff(SyncClock%ECP(n)%EClock)
       if (present(force_stop) .and. present(force_stop_ymd) .and. present(force_stop_tod)) then
          if (force_stop) then
             if (n == 1 .and. seq_comm_iamroot(CPLID)) then
                write(logunit,*) subname,'force stop at ',force_stop_ymd, force_stop_tod
             endif
             if (force_stop_ymd < 0 .or. force_stop_tod < 0) then
                call shr_sys_abort(subname//': force_stop_ymd, force_stop_tod invalid')
             endif
             seq_timemgr_end_restart = .true.
             call seq_timemgr_ETimeInit(NextAlarm, force_stop_ymd, force_stop_tod, "optDate")
             CALL ESMF_AlarmSet( SyncClock%EAlarm(n,seq_timemgr_nalarm_datestop),  &
                  name = trim(seq_timemgr_alarm_datestop), &
                  RingTime=NextAlarm,        &
                  rc=rc )
          endif
       endif
    enddo

    ! --- advance driver clock and all driver alarms ---

    call ESMF_ClockAdvance( SyncClock%ECP(seq_timemgr_nclock_drv)%EClock, rc=rc )
    call seq_timemgr_ESMFCodeCheck( rc, msg=subname//"Error from drv ESMF_ClockAdvance")

    ! --- advance other clocks if driver component run alarm is ringing ---

    if (ESMF_AlarmIsRinging(SyncClock%EAlarm(seq_timemgr_nclock_drv,seq_timemgr_nalarm_atmrun))) then
       call ESMF_ClockAdvance(SyncClock%ECP(seq_timemgr_nclock_atm)%EClock, rc=rc )
       call seq_timemgr_ESMFCodeCheck(rc, msg=subname//"Error from atm ESMF_ClockAdvance")
    endif

    if (ESMF_AlarmIsRinging(SyncClock%EAlarm(seq_timemgr_nclock_drv,seq_timemgr_nalarm_lndrun))) then
       call ESMF_ClockAdvance(SyncClock%ECP(seq_timemgr_nclock_lnd)%EClock, rc=rc )
       call seq_timemgr_ESMFCodeCheck(rc, msg=subname//"Error from lnd ESMF_ClockAdvance")
    endif

    if (ESMF_AlarmIsRinging(SyncClock%EAlarm(seq_timemgr_nclock_drv,seq_timemgr_nalarm_rofrun))) then
       call ESMF_ClockAdvance(SyncClock%ECP(seq_timemgr_nclock_rof)%EClock, rc=rc )
       call seq_timemgr_ESMFCodeCheck(rc, msg=subname//"Error from rof ESMF_ClockAdvance")
    endif

    if (ESMF_AlarmIsRinging(SyncClock%EAlarm(seq_timemgr_nclock_drv,seq_timemgr_nalarm_ocnrun))) then
       call ESMF_ClockAdvance(SyncClock%ECP(seq_timemgr_nclock_ocn)%EClock, rc=rc )
       call seq_timemgr_ESMFCodeCheck(rc, msg=subname//"Error from ocn ESMF_ClockAdvance")
    endif

    if (ESMF_AlarmIsRinging(SyncClock%EAlarm(seq_timemgr_nclock_drv,seq_timemgr_nalarm_icerun))) then
       call ESMF_ClockAdvance(SyncClock%ECP(seq_timemgr_nclock_ice)%EClock, rc=rc )
       call seq_timemgr_ESMFCodeCheck(rc, msg=subname//"Error from ice ESMF_ClockAdvance")
    endif

    if (ESMF_AlarmIsRinging(SyncClock%EAlarm(seq_timemgr_nclock_drv,seq_timemgr_nalarm_glcrun))) then
       call ESMF_ClockAdvance(SyncClock%ECP(seq_timemgr_nclock_glc)%EClock, rc=rc )
       call seq_timemgr_ESMFCodeCheck(rc, msg=subname//"Error from glc ESMF_ClockAdvance")
    endif

    if (ESMF_AlarmIsRinging(SyncClock%EAlarm(seq_timemgr_nclock_drv,seq_timemgr_nalarm_wavrun))) then
       call ESMF_ClockAdvance(SyncClock%ECP(seq_timemgr_nclock_wav)%EClock, rc=rc )
       call seq_timemgr_ESMFCodeCheck(rc, msg=subname//"Error from wav ESMF_ClockAdvance")
    endif

    if (ESMF_AlarmIsRinging(SyncClock%EAlarm(seq_timemgr_nclock_drv,seq_timemgr_nalarm_esprun))) then
       call ESMF_ClockAdvance(SyncClock%ECP(seq_timemgr_nclock_esp)%EClock, rc=rc )
       call seq_timemgr_ESMFCodeCheck(rc, msg=subname//"Error from esp ESMF_ClockAdvance")
    endif

    ! Special handling of ESP component if linked to pause cycles
    if (seq_timemgr_esp_run_on_pause) then
       ! We need to figure out if any pause clock is ringing
       call seq_timemgr_alarmSetOff(SyncClock%ECP(seq_timemgr_nclock_drv)%EClock,seq_timemgr_alarm_esprun)
       if (seq_timemgr_alarmIsOn(SyncClock%ECP(seq_timemgr_pause_sig_index)%EClock,seq_timemgr_alarm_pause)) then
          call seq_timemgr_alarmSetOn(SyncClock%ECP(seq_timemgr_nclock_drv)%EClock,seq_timemgr_alarm_esprun)
       end if
    end if

    ! Special handling of restart alarm if end_restart is .true.
    if (seq_timemgr_end_restart) then
       do n = 1,max_clocks
          if (seq_timemgr_alarmIsOn(SyncClock%ECP(n)%EClock,seq_timemgr_alarm_stop) .or. &
               seq_timemgr_alarmIsOn(SyncClock%ECP(n)%EClock,seq_timemgr_alarm_datestop)) then
             call seq_timemgr_alarmSetOn(SyncClock%ECP(n)%EClock,seq_timemgr_alarm_restart)
          endif
       enddo
    endif

  end subroutine seq_timemgr_clockAdvance

  !===============================================================================
  !===============================================================================
  ! !IROUTINE: seq_timemgr_alarmInit -- Set an alarm
  !
  ! !DESCRIPTION:
  !
  !     Setup an alarm in a clock
  !
  ! !INTERFACE: ------------------------------------------------------------------

  subroutine seq_timemgr_alarmInit( EClock, EAlarm, option, opt_n, opt_ymd, opt_tod, RefTime, cplTimeStep, alarmname)

    implicit none

    ! !INPUT/OUTPUT PARAMETERS:

    type(ESMF_Clock)             , intent(INOUT) :: EClock    ! clock
    type(ESMF_Alarm)             , intent(INOUT) :: EAlarm    ! alarm
    character(len=*)             , intent(IN)    :: option    ! alarm option
    integer(SHR_KIND_IN),optional, intent(IN)    :: opt_n     ! alarm freq
    integer(SHR_KIND_IN),optional, intent(IN)    :: opt_ymd   ! alarm ymd
    integer(SHR_KIND_IN),optional, intent(IN)    :: opt_tod   ! alarm tod (sec)
    type(ESMF_TimeInterval), optional, intent(IN) :: CplTimeStep ! coupler timestep for nstep alarm option
    type(ESMF_Time)     ,optional, intent(IN)    :: RefTime   ! ref time
    character(len=*)    ,optional, intent(IN)    :: alarmname ! alarm name

    !----- local -----
    character(len=*), parameter :: subname = '(seq_timemgr_alarmInit): '
    integer :: rc                             ! Return code
    integer :: lymd                           ! local ymd
    integer :: ltod                           ! local tod
    integer :: cyy,cmm,cdd,csec               ! time info
    integer :: nyy,nmm,ndd,nsec               ! time info
    character(len=64) :: lalarmname           ! local alarm name
    logical :: update_nextalarm               ! update next alarm
    type(ESMF_Time) :: CurrTime               ! Current Time
    type(ESMF_Time) :: NextAlarm              ! Next restart alarm time
    type(ESMF_TimeInterval) :: AlarmInterval  ! Alarm interval

    !-------------------------------------------------------------------------------
    ! Notes: This is slightly screwed up because of the way the ESMF alarm
    !        initializes.  The ringtime sent to AlarmCreate MUST be the next
    !        alarm time.  If you send an arbitrary but proper ringtime from
    !        the past and the ring interval, the alarm will always go off on
    !        the next clock advance and this will cause serious problems.
    !        So, even if it makes sense to initialize an alarm with some
    !        reference time and the alarm interval, that reference time has
    !        to be advance forward to be >= the current time.  In the logic
    !        below, we set an appropriate "NextAlarm" and then we make sure
    !        to advance it properly based on the ring interval.
    !-------------------------------------------------------------------------------

    lalarmname = 'alarm_unknown'
    if (present(alarmname)) then
       lalarmname = trim(alarmname)
    endif

    ltod = 0
    if (present(opt_tod)) then
       ltod = opt_tod
    endif

    lymd = -1
    if (present(opt_ymd)) then
       lymd = opt_ymd
    endif

    call ESMF_ClockGet(EClock, CurrTime=CurrTime, rc=rc)
    call ESMF_TimeGet(CurrTime, yy=cyy, mm=cmm, dd=cdd, s=csec, rc=rc )

    ! --- initial guess of next alarm, this will be updated below ---
    if (present(RefTime)) then
       NextAlarm = RefTime
    else
       NextAlarm = CurrTime
    endif
    call ESMF_TimeGet(CurrTime, yy=nyy, mm=nmm, dd=ndd, s=nsec, rc=rc )

    update_nextalarm  = .true.

    selectcase (trim(option))

    case (seq_timemgr_optNONE)
       !--- tcx seems we need an alarm interval or the alarm create fails,
       !--- problem in esmf_wrf_timemgr?
       call ESMF_TimeIntervalSet(AlarmInterval, yy=9999, rc=rc)
       call ESMF_TimeSet( NextAlarm, yy=9999, mm=12, dd=1, s=0, calendar=seq_timemgr_cal, rc=rc )
       update_nextalarm  = .false.

    case (seq_timemgr_optNever)
       !--- tcx seems we need an alarm interval or the alarm create fails,
       !--- problem in esmf_wrf_timemgr?
       call ESMF_TimeIntervalSet(AlarmInterval, yy=9999, rc=rc)
       call ESMF_TimeSet( NextAlarm, yy=9999, mm=12, dd=1, s=0, calendar=seq_timemgr_cal, rc=rc )
       update_nextalarm  = .false.

    case (seq_timemgr_optDate)
       !--- tcx seems we need an alarm interval or the alarm create fails,
       !--- problem in esmf_wrf_timemgr?
       call ESMF_TimeIntervalSet(AlarmInterval, yy=9999, rc=rc)
       if (.not. present(opt_ymd)) call shr_sys_abort(subname//trim(option)//' requires opt_ymd')
       if (lymd < 0 .or. ltod < 0) then
          call shr_sys_abort(subname//trim(option)//'opt_ymd, opt_tod invalid')
       endif
       call seq_timemgr_ETimeInit(NextAlarm, lymd, ltod, "optDate")
       update_nextalarm  = .false.

    case (seq_timemgr_optIfdays0)
       call ESMF_TimeIntervalSet(AlarmInterval, mm=1, rc=rc)
       if (.not. present(opt_ymd)) call shr_sys_abort(subname//trim(option)//' requires opt_ymd')
       if (.not.present(opt_n)) call shr_sys_abort(subname//trim(option)//' requires opt_n')
       if (opt_n <= 0)  call shr_sys_abort(subname//trim(option)//' invalid opt_n')
       call ESMF_TimeSet( NextAlarm, yy=cyy, mm=cmm, dd=opt_n, s=0, calendar=seq_timemgr_cal, rc=rc )

    case (seq_timemgr_optNSteps)
       if (present(CplTimeStep)) then
          AlarmInterval = CplTimeStep
       else
          call shr_sys_abort(subname//trim(option)//' requires CplTimeStep')
       endif
       if (.not.present(opt_n)) call shr_sys_abort(subname//trim(option)//' requires opt_n')
       if (opt_n <= 0)  call shr_sys_abort(subname//trim(option)//' invalid opt_n')
       AlarmInterval = AlarmInterval * opt_n

    case (seq_timemgr_optNStep)
       if (present(CplTimeStep)) then
          AlarmInterval = CplTimeStep
       else
          call shr_sys_abort(subname//trim(option)//' requires CplTimeStep')
       endif
       if (.not.present(opt_n)) call shr_sys_abort(subname//trim(option)//' requires opt_n')
       if (opt_n <= 0)  call shr_sys_abort(subname//trim(option)//' invalid opt_n')
       AlarmInterval = AlarmInterval * opt_n

    case (seq_timemgr_optNSeconds)
       call ESMF_TimeIntervalSet(AlarmInterval, s=1, rc=rc)
       if (.not.present(opt_n)) call shr_sys_abort(subname//trim(option)//' requires opt_n')
       if (opt_n <= 0)  call shr_sys_abort(subname//trim(option)//' invalid opt_n')
       AlarmInterval = AlarmInterval * opt_n

    case (seq_timemgr_optNSecond)
       call ESMF_TimeIntervalSet(AlarmInterval, s=1, rc=rc)
       if (.not.present(opt_n)) call shr_sys_abort(subname//trim(option)//' requires opt_n')
       if (opt_n <= 0)  call shr_sys_abort(subname//trim(option)//' invalid opt_n')
       AlarmInterval = AlarmInterval * opt_n

    case (seq_timemgr_optNMinutes)
       call ESMF_TimeIntervalSet(AlarmInterval, s=60, rc=rc)
       if (.not.present(opt_n)) call shr_sys_abort(subname//trim(option)//' requires opt_n')
       if (opt_n <= 0)  call shr_sys_abort(subname//trim(option)//' invalid opt_n')
       AlarmInterval = AlarmInterval * opt_n

    case (seq_timemgr_optNMinute)
       call ESMF_TimeIntervalSet(AlarmInterval, s=60, rc=rc)
       if (.not.present(opt_n)) call shr_sys_abort(subname//trim(option)//' requires opt_n')
       if (opt_n <= 0)  call shr_sys_abort(subname//trim(option)//' invalid opt_n')
       AlarmInterval = AlarmInterval * opt_n

    case (seq_timemgr_optNHours)
       call ESMF_TimeIntervalSet(AlarmInterval, s=3600, rc=rc)
       if (.not.present(opt_n)) call shr_sys_abort(subname//trim(option)//' requires opt_n')
       if (opt_n <= 0)  call shr_sys_abort(subname//trim(option)//' invalid opt_n')
       AlarmInterval = AlarmInterval * opt_n

    case (seq_timemgr_optNHour)
       call ESMF_TimeIntervalSet(AlarmInterval, s=3600, rc=rc)
       if (.not.present(opt_n)) call shr_sys_abort(subname//trim(option)//' requires opt_n')
       if (opt_n <= 0)  call shr_sys_abort(subname//trim(option)//' invalid opt_n')
       AlarmInterval = AlarmInterval * opt_n

    case (seq_timemgr_optNDays)
       call ESMF_TimeIntervalSet(AlarmInterval, d=1, rc=rc)
       if (.not.present(opt_n)) call shr_sys_abort(subname//trim(option)//' requires opt_n')
       if (opt_n <= 0)  call shr_sys_abort(subname//trim(option)//' invalid opt_n')
       AlarmInterval = AlarmInterval * opt_n
       !       call ESMF_TimeSet( NextAlarm, yy=cyy, mm=cmm, dd=cdd, s=0, calendar=seq_timemgr_cal, rc=rc )

    case (seq_timemgr_optNDay)
       call ESMF_TimeIntervalSet(AlarmInterval, d=1, rc=rc)
       if (.not.present(opt_n)) call shr_sys_abort(subname//trim(option)//' requires opt_n')
       if (opt_n <= 0)  call shr_sys_abort(subname//trim(option)//' invalid opt_n')
       AlarmInterval = AlarmInterval * opt_n
       !       call ESMF_TimeSet( NextAlarm, yy=cyy, mm=cmm, dd=cdd, s=0, calendar=seq_timemgr_cal, rc=rc )

    case (seq_timemgr_optNMonths)
       call ESMF_TimeIntervalSet(AlarmInterval, mm=1, rc=rc)
       if (.not.present(opt_n)) call shr_sys_abort(subname//trim(option)//' requires opt_n')
       if (opt_n <= 0)  call shr_sys_abort(subname//trim(option)//' invalid opt_n')
       AlarmInterval = AlarmInterval * opt_n
       !       call ESMF_TimeSet( NextAlarm, yy=cyy, mm=cmm, dd=1, s=0, calendar=seq_timemgr_cal, rc=rc )

    case (seq_timemgr_optNMonth)
       call ESMF_TimeIntervalSet(AlarmInterval, mm=1, rc=rc)
       if (.not.present(opt_n)) call shr_sys_abort(subname//trim(option)//' requires opt_n')
       if (opt_n <= 0)  call shr_sys_abort(subname//trim(option)//' invalid opt_n')
       AlarmInterval = AlarmInterval * opt_n
       !       call ESMF_TimeSet( NextAlarm, yy=cyy, mm=cmm, dd=1, s=0, calendar=seq_timemgr_cal, rc=rc )

    case (seq_timemgr_optMonthly)
       call ESMF_TimeIntervalSet(AlarmInterval, mm=1, rc=rc)
       call ESMF_TimeSet( NextAlarm, yy=cyy, mm=cmm, dd=1, s=0, calendar=seq_timemgr_cal, rc=rc )

    case (seq_timemgr_optNYears)
       call ESMF_TimeIntervalSet(AlarmInterval, yy=1, rc=rc)
       if (.not.present(opt_n)) call shr_sys_abort(subname//trim(option)//' requires opt_n')
       if (opt_n <= 0)  call shr_sys_abort(subname//trim(option)//' invalid opt_n')
       AlarmInterval = AlarmInterval * opt_n
       !       call ESMF_TimeSet( NextAlarm, yy=cyy, mm=1, dd=1, s=0, calendar=seq_timemgr_cal, rc=rc )

    case (seq_timemgr_optNYear)
       call ESMF_TimeIntervalSet(AlarmInterval, yy=1, rc=rc)
       if (.not.present(opt_n)) call shr_sys_abort(subname//trim(option)//' requires opt_n')
       if (opt_n <= 0)  call shr_sys_abort(subname//trim(option)//' invalid opt_n')
       AlarmInterval = AlarmInterval * opt_n
       !       call ESMF_TimeSet( NextAlarm, yy=cyy, mm=1, dd=1, s=0, calendar=seq_timemgr_cal, rc=rc )

    case (seq_timemgr_optYearly)
       call ESMF_TimeIntervalSet(AlarmInterval, yy=1, rc=rc)
       call ESMF_TimeSet( NextAlarm, yy=cyy, mm=1, dd=1, s=0, calendar=seq_timemgr_cal, rc=rc )

    case (seq_timemgr_optEnd)
       call shr_sys_abort(subname//'deprecated option '//trim(option))

    case default
       call shr_sys_abort(subname//'unknown option '//trim(option))

    end select

    ! --------------------------------------------------------------------------------
    ! --- AlarmInterval and NextAlarm should be set ---
    ! --------------------------------------------------------------------------------

    ! --- advance Next Alarm so it won't ring on first timestep for
    ! --- most options above. go back one alarminterval just to be careful

    if (update_nextalarm) then
       NextAlarm = NextAlarm - AlarmInterval
       do while (NextAlarm <= CurrTime)
          NextAlarm = NextAlarm + AlarmInterval
       enddo
    endif

    EAlarm = ESMF_AlarmCreate( name=lalarmname, clock=EClock, ringTime=NextAlarm, &
         ringInterval=AlarmInterval, rc=rc)
    call seq_timemgr_ESMFCodeCheck( rc, msg=subname//"Error from ESMF_AlarmCreate" )

  end subroutine seq_timemgr_AlarmInit

  !===============================================================================
  !===============================================================================
  ! !IROUTINE: seq_timemgr_alarmGet -- Get information from the alarm
  !
  ! !DESCRIPTION:
  !
  !     Get various values from the alarm.
  !
  ! !INTERFACE: ------------------------------------------------------------------

  subroutine seq_timemgr_alarmGet( EAlarm, next_ymd, next_tod, prev_ymd, prev_tod,    &
       IntSec, IntMon, IntYrs, name)

    implicit none

    ! !INPUT/OUTPUT PARAMETERS:

    type(ESMF_Alarm)    , intent(INOUT)            :: EAlarm   ! Input Alarm object
    integer(SHR_KIND_IN), intent(OUT), optional :: next_ymd ! alarm date yyyymmdd
    integer(SHR_KIND_IN), intent(OUT), optional :: next_tod ! alarm tod sec
    integer(SHR_KIND_IN), intent(OUT), optional :: prev_ymd ! alarm date yyyymmdd
    integer(SHR_KIND_IN), intent(OUT), optional :: prev_tod ! alarm tod sec
    integer(SHR_KIND_IN), intent(OUT), optional :: IntSec   ! alarm int sec
    integer(SHR_KIND_IN), intent(OUT), optional :: IntMon   ! alarm int mon
    integer(SHR_KIND_IN), intent(OUT), optional :: IntYrs   ! alarm int yrs
    character(len=*)    , intent(OUT), optional :: name     ! alarm name

    !----- local -----
    character(len=*), parameter :: subname = '(seq_timemgr_alarmGet) '
    integer :: yy, mm, dd, sec                ! Return time values
    integer :: ymd                            ! Date (YYYYMMDD)
    integer :: tod                            ! time of day (sec)
    integer :: rc                             ! error code
    type(ESMF_TimeInterval) :: alarmInterval  ! Alarm interval
    type(ESMF_Time) :: ringTime               ! Next alarm ring time

    !-------------------------------------------------------------------------------
    ! Notes:
    !-------------------------------------------------------------------------------

    if (present(name)) then
       call ESMF_AlarmGet( EAlarm, name=name, rc=rc)
       call seq_timemgr_ESMFCodeCheck( rc, msg=subname//"Error from ESMF_AlarmGet name" )
    endif

    call ESMF_AlarmGet( EAlarm, RingTime=RingTime, rc=rc )
    call seq_timemgr_ESMFCodeCheck( rc, msg=subname//"Error from ESMF_AlarmGet RingTime" )
    call seq_timemgr_ETimeGet( RingTime, ymd=ymd, tod=tod)
    if ( present(next_ymd) ) next_ymd = ymd
    if ( present(next_tod) ) next_tod = tod

    call ESMF_AlarmGet( EAlarm, PrevRingTime=RingTime, rc=rc )
    call seq_timemgr_ESMFCodeCheck( rc, msg=subname//"Error from ESMF_AlarmGet PrevRingTime")
    call seq_timemgr_ETimeGet( RingTime, ymd=ymd, tod=tod)
    if ( present(prev_ymd) ) prev_ymd = ymd
    if ( present(prev_tod) ) prev_tod = tod

    yy = 0
    mm = 0
    dd = 0
    sec = 0
    call ESMF_AlarmGet( EAlarm, RingInterval=AlarmInterval, rc=rc )
    call seq_timemgr_ESMFCodeCheck( rc, msg=subname//"Error from ESMF_AlarmGet RingInterval")
    call ESMF_TimeIntervalGet( alarmInterval, yy=yy, mm=mm, d=dd, s=sec, rc=rc )
    call seq_timemgr_ESMFCodeCheck( rc, msg=subname//"Error from ESMF_TimeIntervalGet" )
    sec = sec + dd*(SecPerDay)

    ! --- If want restart next interval information -------------------------
    if ( present(IntSec) ) IntSec = sec
    if ( present(IntMon) ) IntMon = mm
    if ( present(IntYrs) ) IntYrs = yy

  end subroutine seq_timemgr_alarmGet
  !===============================================================================
  !===============================================================================
  ! !IROUTINE: seq_timemgr_alarmSetOn -- turn alarm on
  !
  ! !DESCRIPTION:
  !
  !     turn alarm on
  !
  ! !INTERFACE: ------------------------------------------------------------------

  subroutine seq_timemgr_AlarmSetOn( EClock, alarmname)

    implicit none

    ! !INPUT/OUTPUT PARAMETERS:

    type(ESMF_Clock), intent(INOUT) :: EClock      ! clock/alarm
    character(len=*), intent(IN), optional :: alarmname  ! alarmname

    !----- local -----
    character(len=*), parameter :: subname = '(seq_timemgr_alarmSetOn) '
    character(len=*), parameter :: xalarm = 'unset'
    integer :: n
    integer :: rc
    logical :: found
    logical :: set
    character(len=64) :: name
    type(ESMF_Alarm),pointer :: EAlarm_list(:)
    integer(SHR_KIND_IN) :: AlarmCount ! Number of valid alarms

    !-------------------------------------------------------------------------------
    ! Notes: The Alarm_list is returned and only a subset of the alarms may
    !   be initialized.  In the esmf_wrf_timemgr, numalarms is not used internally,
    !   and the alarm pointer is valid if it's associated.  If it's not associated
    !   the AlarmGet calls will generally return an error code.  What we really
    !   want is to ignore the unset alarms.  So below, we have to kind of kludge
    !   this up.  We set name=xalarm, a special value, before the AlarmGet call so
    !   if Alarm_list(n) is not associated, the name will remain the value of
    !   xalarm.  Then we check whether it's a valid alarm by first checking
    !   the name vs xalarm.  If name is not xalarm, then it must be a valid alarm
    !   and we either set found to true if we are setting all alarms or we compare
    !   the name returned to the alarm name we're looking for and only set found
    !   to true if the names match.
    !-------------------------------------------------------------------------------

    set = .false.

    call seq_timemgr_EClockGetData(EClock, AlarmCount=AlarmCount)
#ifdef USE_ESMF_LIB
    allocate(EAlarm_list(AlarmCount))
    call ESMF_ClockGetAlarmList(EClock, alarmListFlag=ESMF_ALARMLIST_ALL, &
         alarmList=EAlarm_list, alarmCount=AlarmCount, rc=rc)
#else
    call ESMF_ClockGetAlarmList(EClock, EAlarm_list, rc=rc)
#endif
    call seq_timemgr_ESMFCodeCheck( rc, msg=subname//"Error from ESMF_ClockGetAlarmList" )
    do n = 1,AlarmCount
       found = .false.
       if (present(alarmname)) then
          call ESMF_AlarmGet(EAlarm_list(n), name=name)
          if (trim(name) == trim(alarmname)) found = .true.
       else
          found = .true.
       endif
       if (found) then
          set = .true.
          call ESMF_AlarmRingerOn( EAlarm_list(n), rc=rc )
          call seq_timemgr_ESMFCodeCheck( rc, msg=subname//"Error from ESMF_AlarmRingerOn" )
       endif
    enddo

    if (present(alarmname) .and. .not. set) then
       write(logunit,*) subname,' ERROR in alarmname ',trim(alarmname)
       call shr_sys_abort()
    endif
#ifdef USE_ESMF_LIB
    deallocate(EAlarm_list)
#endif

  end subroutine seq_timemgr_AlarmSetOn

  !===============================================================================
  !===============================================================================
  ! !IROUTINE: seq_timemgr_alarmSetOff -- turn alarm off
  !
  ! !DESCRIPTION:
  !
  !     turn alarm off
  !
  ! !INTERFACE: ------------------------------------------------------------------

  subroutine seq_timemgr_AlarmSetOff( EClock, alarmname)

    implicit none

    ! !INPUT/OUTPUT PARAMETERS:

    type(ESMF_Clock), intent(INOUT) :: EClock      ! clock/alarm
    character(len=*), intent(IN), optional :: alarmname  ! alarmname

    !----- local -----
    character(len=*), parameter :: subname = '(seq_timemgr_alarmSetOff) '
    character(len=*), parameter :: xalarm = 'unset'
    integer :: n
    integer :: rc
    logical :: found
    logical :: set
    character(len=64) :: name
    type(ESMF_Alarm),pointer :: EAlarm_list(:)
    integer(SHR_KIND_IN) :: AlarmCount ! Number of valid alarms

    !-------------------------------------------------------------------------------
    ! Notes: The Alarm_list is returned and only a subset of the alarms may
    !   be initialized.  In the esmf_wrf_timemgr, numalarms is not used internally,
    !   and the alarm pointer is valid if it's associated.  If it's not associated
    !   the AlarmGet calls will generally return an error code.  What we really
    !   want is to ignore the unset alarms.  So below, we have to kind of kludge
    !   this up.  We set name=xalarm, a special value, before the AlarmGet call so
    !   if Alarm_list(n) is not associated, the name will remain the value of
    !   xalarm.  Then we check whether it's a valid alarm by first checking
    !   the name vs xalarm.  If name is not xalarm, then it must be a valid alarm
    !   and we either set found to true if we are setting all alarms or we compare
    !   the name returned to the alarm name we're looking for and only set found
    !   to true if the names match.
    !-------------------------------------------------------------------------------

    set = .false.

    call seq_timemgr_EClockGetData(EClock, AlarmCount=AlarmCount)
#ifdef USE_ESMF_LIB
    allocate(EAlarm_list(AlarmCount))
    call ESMF_ClockGetAlarmList(EClock, alarmListFlag=ESMF_ALARMLIST_ALL, &
         alarmList=EAlarm_list, alarmCount=AlarmCount, rc=rc)
#else
    call ESMF_ClockGetAlarmList(EClock, EAlarm_list, rc=rc)
#endif
    call seq_timemgr_ESMFCodeCheck( rc, msg=subname//"Error from ESMF_ClockGetAlarmList" )
    do n = 1,AlarmCount
       found = .false.
       if (present(alarmname)) then
          call ESMF_AlarmGet(EAlarm_list(n), name=name)
          if (trim(name) == trim(alarmname)) found = .true.
       else
          found = .true.
       endif
       if (found) then
          set = .true.
          call ESMF_AlarmRingerOff( EAlarm_list(n), rc=rc )
          call seq_timemgr_ESMFCodeCheck( rc, msg=subname//"Error from ESMF_AlarmRingerOff" )
       endif
    enddo

    if (present(alarmname) .and. .not. set) then
       write(logunit,*) subname,' ERROR in alarmname ',trim(alarmname)
       call shr_sys_abort()
    endif
#ifdef USE_ESMF_LIB
    deallocate(EAlarm_list)
#endif

  end subroutine seq_timemgr_AlarmSetOff

  !===============================================================================
  !===============================================================================
  ! !IROUTINE: seq_timemgr_alarmIsOn -- check if an alarm is ringing
  !
  ! !DESCRIPTION:
  !
  !     check if an alarm is ringing
  !
  ! !INTERFACE: ------------------------------------------------------------------

  logical function seq_timemgr_alarmIsOn( EClock, alarmname)

    implicit none

    ! !INPUT/OUTPUT PARAMETERS:

    type(ESMF_Clock), intent(IN) :: EClock     ! clock/alarm
    character(len=*), intent(IN) :: alarmname  ! which alarm

    !----- local -----
    character(len=*), parameter :: subname = '(seq_timemgr_alarmIsOn) '
    character(len=*), parameter :: xalarm = 'unset'
    integer :: n
    integer :: rc
    logical :: found
    character(len=64) :: name
    type(ESMF_Time) :: ETime1, ETime2
    type(ESMF_Alarm),pointer :: EAlarm_list(:)
    integer(SHR_KIND_IN) :: AlarmCount ! Number of valid alarms

    !-------------------------------------------------------------------------------
    ! Notes:  Because of the esmf_wrf_timemgr implementation with regards to
    !   valid alarms in the alarm_list, we initialize name to xalarm before
    !   querying the alarm name, and if the alarm is not valid, name will not
    !   be updated and we can tell that the alarm is not valid and we should
    !   just ignore it.
    !         Use found to verify alarm was valid.  If not, abort
    !-------------------------------------------------------------------------------

    seq_timemgr_alarmIsOn = .false.
    found = .false.

    call seq_timemgr_EClockGetData(EClock, AlarmCount=AlarmCount)
#ifdef USE_ESMF_LIB
    allocate(EAlarm_list(AlarmCount))
    call ESMF_ClockGetAlarmList(EClock, alarmListFlag=ESMF_ALARMLIST_ALL, &
         alarmList=EAlarm_list, alarmCount=AlarmCount, rc=rc)
#else
    call ESMF_ClockGetAlarmList(EClock, EAlarm_list, rc=rc)
#endif
    call seq_timemgr_ESMFCodeCheck( rc, msg=subname//"Error from ESMF_ClockGetAlarmList" )
    do n = 1,AlarmCount
       name = trim(xalarm)
       call ESMF_AlarmGet(EAlarm_list(n), name=name)
       if (trim(name) == trim(alarmname)) then
          found = .true.
          seq_timemgr_alarmIsOn = ESMF_AlarmIsRinging(alarm=EAlarm_list(n),rc=rc)
          call seq_timemgr_ESMFCodeCheck( rc, msg=subname// &
               "Error from ESMF_AlarmIsRinging" )
          ! --- make sure the datestop will always stop with dates >= stop_date
          if (trim(alarmname) == trim(seq_timemgr_alarm_datestop)) then
             call ESMF_ClockGet(EClock, CurrTime = ETime1, rc=rc)
             call seq_timemgr_ESMFCodeCheck( rc, msg=subname//"Error from ESMF_ClockGet CurrTime" )
             call ESMF_AlarmGet(EAlarm_list(n), RingTime = ETime2, rc=rc)
             call seq_timemgr_ESMFCodeCheck( rc, msg=subname//"Error from ESMF_AlarmGet RingTime" )
             if (ETime1 >= ETime2) seq_timemgr_alarmIsOn = .true.
          endif
       endif
    enddo

    if (.not.found) then
       write(logunit,*) subname//': ERROR alarm not valid for EClock '//trim(alarmname)
       call shr_sys_abort( subname//'ERROR: alarm invalid '//trim(alarmname) )
    endif
#ifdef USE_ESMF_LIB
    deallocate(EAlarm_list)
#endif

  end function seq_timemgr_alarmIsOn

  !===============================================================================
  !===============================================================================
  ! !IROUTINE: seq_timemgr_restartAlarmIsOn -- check if an alarm is ringing
  !
  ! !DESCRIPTION:
  !
  !     check if an alarm is ringing
  !
  ! !INTERFACE: ------------------------------------------------------------------

  logical function seq_timemgr_restartAlarmIsOn( EClock)

    implicit none

    ! !INPUT/OUTPUT PARAMETERS:

    type(ESMF_Clock) , intent(IN) :: EClock     ! clock/alarm

    !----- local -----
    character(len=*), parameter :: subname = '(seq_timemgr_restartAlarmIsOn) '

    !-------------------------------------------------------------------------------
    ! Notes:
    !-------------------------------------------------------------------------------

    seq_timemgr_restartAlarmIsOn =  &
         seq_timemgr_alarmIsOn(EClock, alarmname=seq_timemgr_alarm_restart)

  end function seq_timemgr_restartAlarmIsOn

  !===============================================================================
  !===============================================================================
  ! !IROUTINE: seq_timemgr_stopAlarmIsOn -- check if an alarm is ringing
  !
  ! !DESCRIPTION:
  !
  !     check if an alarm is ringing
  !
  ! !INTERFACE: ------------------------------------------------------------------

  logical function seq_timemgr_stopAlarmIsOn( EClock)

    implicit none

    ! !INPUT/OUTPUT PARAMETERS:

    type(ESMF_Clock) , intent(IN) :: EClock     ! clock/alarm

    !----- local -----
    character(len=*), parameter :: subname = '(seq_timemgr_stopAlarmIsOn) '

    !-------------------------------------------------------------------------------
    ! Notes:
    !-------------------------------------------------------------------------------

    seq_timemgr_stopAlarmIsOn =  &
         seq_timemgr_alarmIsOn(EClock, alarmname=seq_timemgr_alarm_stop)

  end function seq_timemgr_stopAlarmIsOn

  !===============================================================================
  !===============================================================================
  ! !IROUTINE: seq_timemgr_historyAlarmIsOn -- check if an alarm is ringing
  !
  ! !DESCRIPTION:
  !
  !     check if an alarm is ringing
  !
  ! !INTERFACE: ------------------------------------------------------------------

  logical function seq_timemgr_historyAlarmIsOn( EClock)

    implicit none

    ! !INPUT/OUTPUT PARAMETERS:

    type(ESMF_Clock) , intent(IN) :: EClock     ! clock/alarm

    !----- local -----
    character(len=*), parameter :: subname = '(seq_timemgr_historyAlarmIsOn) '

    !-------------------------------------------------------------------------------
    ! Notes:
    !-------------------------------------------------------------------------------

    seq_timemgr_historyAlarmIsOn =  &
         seq_timemgr_alarmIsOn(EClock, alarmname=seq_timemgr_alarm_history)

  end function seq_timemgr_historyAlarmIsOn

  !===============================================================================
  !===============================================================================
  ! !IROUTINE: seq_timemgr_pauseAlarmIsOn -- check if an alarm is ringing
  !
  ! !DESCRIPTION:
  !
  !     check if an alarm is ringing
  !
  ! !INTERFACE: ------------------------------------------------------------------

  logical function seq_timemgr_pauseAlarmIsOn( EClock)

    implicit none

    ! !INPUT/OUTPUT PARAMETERS:

    type(ESMF_Clock) , intent(IN) :: EClock     ! clock/alarm

    !EOP

    !----- local -----
    character(len=*), parameter :: subname = '(seq_timemgr_pauseAlarmIsOn) '

    !-------------------------------------------------------------------------------
    ! Notes:
    !-------------------------------------------------------------------------------

    seq_timemgr_pauseAlarmIsOn =  &
         seq_timemgr_alarmIsOn(EClock, alarmname=seq_timemgr_alarm_pause)

  end function seq_timemgr_pauseAlarmIsOn

  !===============================================================================
  !===============================================================================
  ! !IROUTINE: seq_timemgr_pause_active -- Is pause/resume active this run?
  !
  ! !DESCRIPTION:
  !
  !     Return .true. if any component is configured for pause/resume
  !
  ! !INTERFACE: ------------------------------------------------------------------

  logical function seq_timemgr_pause_active()

    !    !INPUT/OUTPUT PARAMETERS:

    !EOP

    !-------------------------------------------------------------------------------
    ! Notes:
    !-------------------------------------------------------------------------------

    seq_timemgr_pause_active = ANY(pause_active)

  end function seq_timemgr_pause_active

  !===============================================================================
  !===============================================================================
  ! !IROUTINE: seq_timemgr_pause_component_index -- return an index for a component
  !
  ! !DESCRIPTION:
  !
  !     Look up a component's internal index for faster processing
  !
  ! !INTERFACE: ------------------------------------------------------------------

  integer function seq_timemgr_pause_component_index(component_name)

    !    !INPUT/OUTPUT PARAMETERS:

    character(len=*), intent(IN) :: component_name

    !EOP

    !----- local -----
    integer                     :: ind
    character(len=*), parameter :: subname = '(seq_timemgr_pause_component_index) '

    !-------------------------------------------------------------------------------
    ! Notes:
    !-------------------------------------------------------------------------------
    seq_timemgr_pause_component_index = 0
    do ind = 1, max_clocks
       if (trim(component_name) == trim(seq_timemgr_clocks(ind))) then
          seq_timemgr_pause_component_index = ind
          exit
       end if
    end do
    if (seq_timemgr_pause_component_index < 1) then
       if (trim(component_name) == 'cpl') then
          seq_timemgr_pause_component_index = seq_timemgr_nclock_drv
       end if
    end if
    if (seq_timemgr_pause_component_index < 1) then
       call shr_sys_abort(subname//': No index for component '//trim(component_name))
    end if

  end function seq_timemgr_pause_component_index

  !===============================================================================
  !===============================================================================
  ! !IROUTINE: seq_timemgr_pause_component_active -- Check if component paused
  !
  ! !DESCRIPTION:
  !
  !     Return .true. if component is active in driver pause
  !
  ! !INTERFACE: ------------------------------------------------------------------

  logical function seq_timemgr_pause_component_active(component_index)

    !    !INPUT/OUTPUT PARAMETERS:

    integer, intent(IN) :: component_index

    !EOP

    !----- local -----
    character(len=*), parameter :: subname = '(seq_timemgr_pause_component_active) '

    !-------------------------------------------------------------------------------
    ! Notes:
    !-------------------------------------------------------------------------------

    if ((component_index < 1) .or. (component_index > max_clocks)) then
       call shr_sys_abort(subname//': component_index out of range')
    end if
    seq_timemgr_pause_component_active = pause_active(component_index)

  end function seq_timemgr_pause_component_active

  !===============================================================================
  !===============================================================================
  ! !IROUTINE: seq_timemgr_data_assimilation_active -- Check if component paused
  !
  ! !DESCRIPTION:
  !
  !     Return .true. if component is active in driver pause
  !
  ! !INTERFACE: ------------------------------------------------------------------

  logical function seq_timemgr_data_assimilation_active(component_ntype)

    !    !INPUT/OUTPUT PARAMETERS:

    character(len=3), intent(IN) :: component_ntype

    !EOP

    !----- local -----
    character(len=*), parameter :: subname = '(seq_timemgr_data_assimilation_active) '

    !-------------------------------------------------------------------------------
    ! Notes:
    !-------------------------------------------------------------------------------

    select case(component_ntype)
    case ('atm')
       seq_timemgr_data_assimilation_active = data_assimilation_active(seq_timemgr_nclock_atm)
    case ('cpl')
       seq_timemgr_data_assimilation_active = data_assimilation_active(seq_timemgr_nclock_drv)
    case ('ocn')
       seq_timemgr_data_assimilation_active = data_assimilation_active(seq_timemgr_nclock_ocn)
    case ('wav')
       seq_timemgr_data_assimilation_active = data_assimilation_active(seq_timemgr_nclock_wav)
    case ('glc')
       seq_timemgr_data_assimilation_active = data_assimilation_active(seq_timemgr_nclock_glc)
    case ('ice')
       seq_timemgr_data_assimilation_active = data_assimilation_active(seq_timemgr_nclock_ice)
    case ('rof')
       seq_timemgr_data_assimilation_active = data_assimilation_active(seq_timemgr_nclock_rof)
    case ('lnd')
       seq_timemgr_data_assimilation_active = data_assimilation_active(seq_timemgr_nclock_lnd)
    case ('iac')
       seq_timemgr_data_assimilation_active = data_assimilation_active(seq_timemgr_nclock_iac)
    case ('esp')
       seq_timemgr_data_assimilation_active = .FALSE.
    case default
       call shr_sys_abort(subname//': component_ntype, "'//component_ntype//'" not recognized"')
    end select

  end function seq_timemgr_data_assimilation_active

  !===============================================================================
  !===============================================================================
  ! !IROUTINE: seq_timemgr_ETimeInit -- Create ESMF_Time object based on YMD values
  !
  ! !DESCRIPTION:
  !
  !     Create the ESMF_Time object corresponding to the given input time, given in
  !  YMD (Year Month Day) and TOD (Time-of-day) format.
  ! Set the time by an integer as YYYYMMDD and integer seconds in the day
  !
  ! !INTERFACE: ------------------------------------------------------------------

  subroutine seq_timemgr_ETimeInit( ETime, ymd, tod, desc )

    implicit none

    ! !INPUT/OUTPUT PARAMETERS:

    type(ESMF_Time) , intent(inout) :: ETime     ! Time
    integer         , intent(in)    :: ymd       ! Year, month, day YYYYMMDD
    integer         , intent(in), optional    :: tod       ! Time of day in seconds
    character(len=*), intent(in), optional    :: desc      ! Description of time to set

    !----- local -----
    character(len=*), parameter :: subname = '(seq_timemgr_ETimeInit) '
    integer :: yr, mon, day          ! Year, month, day as integers
    integer :: ltod                  ! local tod
    character(SHR_KIND_CL)  :: ldesc ! local desc
    integer :: rc                    ! return code

    !-------------------------------------------------------------------------------
    ! Notes:
    !-------------------------------------------------------------------------------

    ltod = 0
    if (present(tod)) then
       ltod = tod
    endif

    ldesc = ''
    if (present(desc)) then
       ldesc = desc
    endif

    if ( (ymd < 0) .or. (ltod < 0) .or. (ltod > SecPerDay) )then
       write(logunit,*) subname//': ERROR yymmdd is a negative number or '// &
            'time-of-day out of bounds', ymd, ltod
       call shr_sys_abort( subname//'ERROR: Bad input' )
    end if

    call shr_cal_date2ymd(ymd,yr,mon,day)

    call ESMF_TimeSet( ETime, yy=yr, mm=mon, dd=day, s=ltod, &
         calendar=seq_timemgr_cal, rc=rc )
    call seq_timemgr_ESMFCodeCheck(rc, subname//': error return from '// &
         'ESMF_TimeSet: setting '//trim(ldesc))

  end subroutine seq_timemgr_ETimeInit

  !===============================================================================
  !===============================================================================
  ! !IROUTINE: seq_timemgr_ETimeGet -- Get the date in YYYYMMDD from from ESMF Time
  !
  ! !DESCRIPTION:
  !
  !     Get the date in YYYYMMDD format from a ESMF time object.
  !
  ! !INTERFACE: ------------------------------------------------------------------

  subroutine seq_timemgr_ETimeGet( ETime, offset, ymd, tod )

    implicit none

    ! !INPUT/OUTPUT PARAMETERS:

    type(ESMF_Time),   intent(IN)  :: ETime   ! Input ESMF time
    integer, optional, intent(IN)  :: offset  ! Offset from input time (sec)
    integer, optional, intent(OUT) :: ymd     ! date of day
    integer, optional, intent(OUT) :: tod     ! Time of day

    !----- local -----
    character(len=*), parameter :: subname = '(seq_timemgr_ETimeGet) '
    type(ESMF_Time)         :: ETimeAdd ! ESMF time + offset
    type(ESMF_TimeInterval) :: ETimeOff ! ESMF offset time-interval
    integer                 :: year     ! Year
    integer                 :: month    ! Month
    integer                 :: day      ! Day in month
    integer                 :: sec      ! Day in month
    integer                 :: rc       ! Return code

    !-------------------------------------------------------------------------------
    ! Notes:
    !-------------------------------------------------------------------------------

    ETimeAdd = ETime
    if ( present(offset) )then
       if ( offset > 0 )then
          call ESMF_TimeIntervalSet( ETimeOff, s=offset, rc=rc )
          call seq_timemgr_ESMFCodeCheck( rc, msg=subname// &
               ": Error from ESMF_TimeIntervalSet" )
          ETimeAdd = ETime + ETimeOff
       else if ( offset < 0 )then
          call ESMF_TimeIntervalSet( ETimeOff, s=-offset, rc=rc )
          call seq_timemgr_ESMFCodeCheck( rc, msg=subname// &
               ": Error from ESMF_TimeIntervalSet" )
          ETimeAdd = ETime - ETimeOff
       end if
    end if

    call ESMF_TimeGet( ETimeAdd, yy=year, mm=month, dd=day, s=sec, rc=rc )
    call seq_timemgr_ESMFCodeCheck( rc, msg=subname// &
         ": Error from ESMF_TimeGet" )

    ! shr_cal has restrictions and then "stops", so override that

    if ( present(ymd) ) then
       call shr_cal_ymd2date(year,month,day,ymd)
    endif
    if ( present(tod) ) then
       tod = sec
    endif

  end subroutine seq_timemgr_ETimeGet

  !===============================================================================
  !===============================================================================
  ! !IROUTINE: seq_timemgr_EClockInit -- Initialize the ESMF clock in the shared clock
  !
  ! !DESCRIPTION:
  !
  ! Private method:
  !
  ! Setup the ESMF clock inside the wrapped CIME clock
  !
  ! !INTERFACE: ------------------------------------------------------------------

  subroutine seq_timemgr_EClockInit( TimeStep, StartTime, RefTime, CurrTime, EClock )

    implicit none

    ! !INPUT/OUTPUT PARAMETERS:

    type(ESMF_TimeInterval), intent(IN)  :: TimeStep    ! Time-step of clock
    type(ESMF_Time)        , intent(IN)  :: StartTime   ! Start time
    type(ESMF_Time)        , intent(IN)  :: RefTime     ! Reference time
    type(ESMF_Time)        , intent(IN)  :: CurrTime    ! Current time
    type(ESMF_Clock)       , intent(OUT) :: EClock      ! Output ESMF clock

    !----- local -----
    character(len=*), parameter :: subname = '(seq_timemgr_EClockInit) '
    integer :: rc                             ! ESMF return code
    character(len=SHR_KIND_CL) :: description ! Description of this clock
    type(ESMF_Time) :: clocktime              ! Current time

    !-------------------------------------------------------------------------------
    ! Notes:
    !-------------------------------------------------------------------------------

    description = 'CIME shared Time-manager clock'

    ! ------ Create ESMF Clock with input characteristics -------------------
    ! --- NOTE: StopTime is required in interface but not used, so use  -----
    ! ---       something arbitrary.  Stop handled via alarm            -----

    call seq_timemgr_ETimeInit(clocktime,  99990101, 0, "artificial stop date")

    EClock = ESMF_ClockCreate(name=trim(description), &
         TimeStep=TimeStep, startTime=StartTime, &
         refTime=RefTime, stopTime=clocktime, rc=rc)
    call seq_timemgr_ESMFCodeCheck( rc, msg=subname//': Error from ESMF_ClockCreate')

    ! ------ Advance clock to the current time (in case of a restart) -------
    call ESMF_ClockGet(EClock, currTime=clocktime, rc=rc )
    call seq_timemgr_ESMFCodeCheck(rc, subname//': Error from ESMF_ClockGet')
    do while( clocktime < CurrTime)
       call ESMF_ClockAdvance( EClock, rc=rc )
       call seq_timemgr_ESMFCodeCheck(rc, subname//': Error from ESMF_ClockAdvance')
       call ESMF_ClockGet( EClock, currTime=clocktime )
       call seq_timemgr_ESMFCodeCheck(rc, subname//': Error from ESMF_ClockGet')
    end do

    if (clocktime /= CurrTime) then
       if (loglevel > 0) write(logunit,*) trim(subname), &
            ' : WARNING clocktime and currtime inconsistent'
    endif

  end subroutine seq_timemgr_EClockInit

  !===============================================================================
  !===============================================================================
  ! !IROUTINE: seq_timemgr_EClockDateInSync -- Check that input date in sync with clock
  !
  ! !DESCRIPTION:
  !
  !     Check that the given input date/time is in sync with clock time
  !
  ! !INTERFACE: ------------------------------------------------------------------

  logical function seq_timemgr_EClockDateInSync( EClock, ymd, tod, prev)

    implicit none

    ! !INPUT/OUTPUT PARAMETERS:

    type(ESMF_Clock), intent(IN) :: Eclock   ! Input clock to compare
    integer,          intent(IN) :: ymd     ! Date (YYYYMMDD)
    integer,          intent(IN) :: tod     ! Time of day (sec)
    logical, optional,intent(IN) :: prev    ! If should get previous time

    !----- local -----
    character(len=*), parameter :: subname = "(seq_timemgr_EClockDateInSync) "
    type(ESMF_Time) :: ETime
    integer :: ymd1      ! Date (YYYYMMDD)
    integer :: tod1      ! Time of day
    logical :: previous  ! If need to get previous time for comparison
    integer :: rc        ! error code

    !-------------------------------------------------------------------------------
    ! Notes:
    !-------------------------------------------------------------------------------

    previous = .false.
    if ( present(prev) )then
       previous = prev
    end if

    if (previous )then
       call ESMF_ClockGet( EClock, prevTime=ETime, rc=rc)
    else
       call ESMF_ClockGet( EClock, currTime=ETime, rc=rc)
    end if
    call seq_timemgr_ETimeGet( ETime, ymd=ymd1, tod=tod1 )

    ! --- If current dates agree return true -- else false

    if ( (ymd == ymd1) .and. (tod == tod1) )then
       seq_timemgr_EClockDateInSync = .true.
    else
       seq_timemgr_EClockDateInSync = .false.
    end if

  end function seq_timemgr_EClockDateInSync

  !===============================================================================
  !===============================================================================
  ! !IROUTINE: seq_timemgr_clockPrint -- Print clock information out
  !
  ! !DESCRIPTION:
  !
  !      Print clock information out.
  !
  ! !INTERFACE: ------------------------------------------------------------------

  subroutine seq_timemgr_clockPrint( SyncClock )

    implicit none

    ! !INPUT/OUTPUT PARAMETERS:

    type(seq_timemgr_type), intent(in) :: SyncClock   ! Input clock to print

    character(len=*), parameter :: subname = "(seq_timemgr_clockPrint) "
    integer(SHR_KIND_IN) :: m,n
    integer(SHR_KIND_IN) :: curr_ymd   ! Current date YYYYMMDD
    integer(SHR_KIND_IN) :: curr_tod   ! Current time of day (s)
    integer(SHR_KIND_IN) :: StepNo     ! Number of steps taken
    integer(SHR_KIND_IN) :: start_ymd  ! Starting date YYYYMMDD
    integer(SHR_KIND_IN) :: start_tod  ! Starting time-of-day (s)
    integer(SHR_KIND_IN) :: stop_ymd   ! Stop date YYYYMMDD
    integer(SHR_KIND_IN) :: stop_tod   ! Stop time-of-day (s)
    integer(SHR_KIND_IN) :: ref_ymd    ! Reference date YYYYMMDD
    integer(SHR_KIND_IN) :: ref_tod    ! Reference time-of-day (s)
    integer(SHR_KIND_IN) :: DTime      ! Time-step (seconds)
    integer(SHR_KIND_IN) :: prev_ymd   ! Prev restart alarm date (YYYYMMDD)
    integer(SHR_KIND_IN) :: prev_tod   ! Prev restart alarm time-of-day (sec)
    integer(SHR_KIND_IN) :: next_ymd   ! Next restart alarm date (YYYYMMDD)
    integer(SHR_KIND_IN) :: next_tod   ! Next restart alarm time-of-day (sec)
    integer(SHR_KIND_IN) :: IntSec     ! Alarm interval for seconds
    integer(SHR_KIND_IN) :: IntMon     ! Alarm interval for months
    integer(SHR_KIND_IN) :: IntYrs     ! Alarm interval for years
    integer(SHR_KIND_IN) :: AlarmCount ! Number of valid alarms
    character(len=64)    :: alarmname  ! Alarm name
    character(len=*), parameter :: xalarm = 'unset'
    type(ESMF_Alarm),pointer :: EAlarm_list(:)   ! EAlarm list associated with EClock
    integer(SHR_KIND_IN) :: rc         ! error code

    character(len=*), parameter ::  F06 = "(2A,L3)"
    character(len=*), parameter ::  F07 = "(3A)"
    character(len=*), parameter ::  F08 = "(2A,I12.8,3x,I5.5)"
    character(len=*), parameter ::  F09 = "(2A,2I8,I12)"
    character(len=*), parameter ::  F10 = "(2A,I2,2x,A)"

    !-------------------------------------------------------------------------------
    ! Notes:
    !-------------------------------------------------------------------------------

    if (loglevel <= 0) return

    write(logunit,F07) subname,'calendar      = ', trim(seq_timemgr_calendar)
    write(logunit,F06) subname,'end_restart   = ', seq_timemgr_end_restart
    write(logunit,F07) ''

    do n = 1,max_clocks
       call seq_timemgr_EClockGetData( SyncClock%ECP(n)%EClock, curr_ymd=curr_ymd, &
            curr_tod=curr_tod, start_ymd=start_ymd,    &
            start_tod=start_tod, StepNo=StepNo,            &
            ref_ymd=ref_ymd, ref_tod=ref_tod,              &
            stop_ymd=stop_ymd, stop_tod=stop_tod,          &
            dtime = dtime, alarmcount=AlarmCount)
#ifdef USE_ESMF_LIB
       allocate(EAlarm_list(AlarmCount))
       call ESMF_ClockGetAlarmList(SyncClock%ECP(n)%EClock, alarmListFlag=ESMF_ALARMLIST_ALL, &
            alarmList=EAlarm_list, alarmCount=AlarmCount, rc=rc)
#else
       call ESMF_ClockGetAlarmList(SyncClock%ECP(n)%EClock, EAlarm_list, rc=rc)
#endif
       call seq_timemgr_ESMFCodeCheck( rc, msg=subname//"Error from ESMF_ClockGetAlarmList" )

       write(logunit,F09) subname,"Clock = "//seq_timemgr_clocks(n),n
       write(logunit,F08) subname,"  Start Time  = ", start_ymd, start_tod
       write(logunit,F08) subname,"  Curr Time   = ", curr_ymd, curr_tod
       write(logunit,F08) subname,"  Ref Time    = ", ref_ymd, ref_tod
       write(logunit,F08) subname,"  Stop Time   = ", stop_ymd, stop_tod
       write(logunit,F09) subname,"  Step number = ", StepNo
       write(logunit,F09) subname,"  Dtime       = ", DTime

       do m = 1,alarmCount
          call seq_timemgr_alarmGet( EAlarm_list(m), &
               next_ymd=next_ymd, next_tod=next_tod, prev_ymd=prev_ymd, prev_tod=prev_tod, &
               IntSec=IntSec, IntMon=IntMon, IntYrs=IntYrs, name=alarmname )
          write(logunit,F10) subname,"  Alarm = ",m,trim(alarmname)
          write(logunit,F08) subname,"    Prev Time   = ", prev_ymd,prev_tod
          write(logunit,F08) subname,"    Next Time   = ", next_ymd,next_tod
          write(logunit,F09) subname,"    Intervl yms = ", IntYrs,IntMon,IntSec
       enddo

       write(logunit,*) ''
#ifdef USE_ESMF_LIB
       deallocate(EAlarm_list)
#endif
    enddo

  end subroutine seq_timemgr_clockPrint

  !===============================================================================
  !===============================================================================
  ! !IROUTINE: seq_timemgr_ESMFDebug -- Print ESMF stuff for debugging
  !
  ! !DESCRIPTION:
  !
  ! Print ESMF stuff for debugging
  !
  ! !INTERFACE: ------------------------------------------------------------------

  subroutine seq_timemgr_ESMFDebug( EClock, ETime, ETimeInterval, istring )

    implicit none

    ! !INPUT/OUTPUT PARAMETERS:

    type(ESMF_Clock), optional, intent(in) :: EClock    ! ESMF Clock
    type(ESMF_Time) , optional, intent(inout) :: ETime     ! ESMF Time
    type(ESMF_TimeInterval), optional, intent(inout) :: ETimeInterval  ! ESMF Time Interval
    character(len=*), optional, intent(in) :: istring

    !----- local -----
    character(len=*), parameter :: subname = '(seq_timemgr_ESMFDebug) '
    character(len=128) :: timestring
    integer :: yy,mm,dd,s            ! ymds
    type(ESMF_Time) :: LTime
    type(ESMF_TimeInterval) :: LTimeInterval
    integer(SHR_KIND_I8) :: LStep
    integer :: rc                    ! return code

    !-------------------------------------------------------------------------------
    ! Notes:
    !-------------------------------------------------------------------------------

    if (present(ETime)) then
       write(logunit,*) subname,' ETime ',trim(istring)
       call ESMF_TimeGet(ETime, yy=yy,mm=mm,dd=dd,s=s,timestring=timestring,rc=rc)
       write(logunit,*) subname,rc,'ymds=',yy,mm,dd,s,trim(timestring)
    endif

    if (present(ETimeInterval)) then
       write(logunit,*) subname,' ETimeInterval ',trim(istring)
       call ESMF_TimeIntervalGet(ETimeInterval, yy=yy,mm=mm,d=dd,s=s,timestring=timestring,rc=rc)
       write(logunit,*) subname,rc,'ymds=',yy,mm,dd,s,trim(timestring)
    endif

    if (present(EClock)) then
       write(logunit,*) subname,' EClock ',trim(istring)
       call ESMF_ClockGet( EClock, StartTime=LTime )
       call ESMF_TimeGet(LTime, yy=yy,mm=mm,dd=dd,s=s,timestring=timestring,rc=rc)
       write(logunit,*) subname,rc,'start ymds=',yy,mm,dd,s,trim(timestring)
       call ESMF_ClockGet( EClock, CurrTime=LTime )
       call ESMF_TimeGet(LTime, yy=yy,mm=mm,dd=dd,s=s,timestring=timestring,rc=rc)
       write(logunit,*) subname,rc,'curr ymds=',yy,mm,dd,s,trim(timestring)
       call ESMF_ClockGet( EClock, StopTime=LTime )
       call ESMF_TimeGet(LTime, yy=yy,mm=mm,dd=dd,s=s,timestring=timestring,rc=rc)
       write(logunit,*) subname,rc,'stop ymds=',yy,mm,dd,s,trim(timestring)
       call ESMF_ClockGet( EClock, PrevTime=LTime )
       call ESMF_TimeGet(LTime, yy=yy,mm=mm,dd=dd,s=s,timestring=timestring,rc=rc)
       write(logunit,*) subname,rc,'prev ymds=',yy,mm,dd,s,trim(timestring)
       call ESMF_ClockGet( EClock, RefTime=LTime )
       call ESMF_TimeGet(LTime, yy=yy,mm=mm,dd=dd,s=s,timestring=timestring,rc=rc)
       write(logunit,*) subname,rc,'ref ymds=',yy,mm,dd,s,trim(timestring)
       call ESMF_ClockGet( EClock, TimeStep=LTimeInterval )
       call ESMF_TimeIntervalGet(LTimeInterval, yy=yy,mm=mm,d=dd,s=s,timestring=timestring,rc=rc)
       write(logunit,*) subname,rc,'tint ymds=',yy,mm,dd,s,trim(timestring)
       call ESMF_ClockGet( EClock, AdvanceCount=LStep )
       write(logunit,*) subname,rc,'advcnt =',LStep
    endif

  end subroutine seq_timemgr_ESMFDebug

  !===============================================================================
  !===============================================================================
  ! !IROUTINE: seq_timemgr_ESMFCodeCheck -- Check return-code from ESMF -- abort if not
  !
  ! !DESCRIPTION:
  !
  !     Check ESMF return code and abort if not successful.
  !
  ! !INTERFACE: ------------------------------------------------------------------

  subroutine seq_timemgr_ESMFCodeCheck( rc, msg )

    ! !USES:

    implicit none

    ! !INPUT/OUTPUT PARAMETERS:

    integer, intent(in)          :: rc   ! return code from ESMF
    character(len=*),optional,intent(in) :: msg  ! error message

    character(len=*),parameter :: subname = 'seq_timemgr_ESMFCodeCheck'
    !-------------------------------------------------------------------------------
    ! Notes:
    !-------------------------------------------------------------------------------

    if ( rc == ESMF_SUCCESS ) return
    if ( present(msg)) then
       write(logunit,*) trim(subname),' error= ',rc,trim(msg)
    else
       write(logunit,*) trim(subname),' error= ',rc
    endif
    call shr_sys_flush(logunit)
    call shr_sys_abort(trim(subname))

  end subroutine seq_timemgr_ESMFCodeCheck

  !===============================================================================
  !===============================================================================

end module seq_timemgr_mod
back to top