!===============================================================================
! SVN $Id: seq_timemgr_mod.F90 23519 2010-06-03 20:54:46Z jwolfe $
! SVN $URL: https://svn-ccsm-models.cgd.ucar.edu/drv/seq_mct/branch_tags/cesm1_0_rel_tags/cesm1_0_rel01_drvseq3_1_32/shr/seq_timemgr_mod.F90 $
!===============================================================================
!BOP ===========================================================================
!
! !MODULE: seq_timemgr_mod --- Time-manager module
!
! !DESCRIPTION:
!
! A module to create derived types to manage time and clock information
! for use with CCSM 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 9,5
! !USES:
use ESMF_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
use shr_sys_mod
, only: shr_sys_abort, shr_sys_flush
use shr_cal_mod
, only: shr_cal_ymd2date, shr_cal_date2ymd, shr_cal_set
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_clockRestart ! Read/Write restart file
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
! --- For usability, built on interfaces above ---
public :: seq_timemgr_restartAlarmIsOn ! Is a restart alarm ringing
public :: seq_timemgr_restartAlarmSetOff ! Turn off restart alarm
public :: seq_timemgr_runAlarmIsOn ! Is a run alarm ringing
public :: seq_timemgr_runAlarmSetOff ! Turn off run alarm
public :: seq_timemgr_stopAlarmIsOn ! Is a stop alarm ringing
public :: seq_timemgr_historyAlarmIsOn ! Is a history alarm ringing
public :: seq_timemgr_historyAlarmSetOff ! Turn off history alarm
! ! 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
! 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_ocn
! seq_timemgr_clock_ice
! seq_timemgr_clock_glc
! 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_ocnrun
! seq_timemgr_alarm_icerun
! seq_timemgr_alarm_glcrun
! seq_timemgr_alarm_ocnnext
! seq_timemgr_alarm_tprof
! seq_timemgr_alarm_histavg
!EOP
private:: seq_timemgr_alarmGet
private:: seq_timemgr_alarmInit
private:: seq_timemgr_ETimeInit
private:: seq_timemgr_ETimeGet
private:: seq_timemgr_EClockInit
private:: seq_timemgr_ESMFDebug
private:: seq_timemgr_ESMFCodeCheck
character(len=*), private, parameter :: &
seq_timemgr_noLeap = "NO_LEAP" , &
seq_timemgr_gregorian = "GREGORIAN" , &
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"
integer(SHR_KIND_IN),private,parameter :: max_clocks = 6
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'
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
character(len=8),private,parameter :: seq_timemgr_clocks(max_clocks) = &
(/'drv ','atm ','lnd ','ocn ', &
'ice ','glc '/)
integer(SHR_KIND_IN),private,parameter :: max_alarms = 13
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_ocnnext = 'seq_timemgr_alarm_ocnnext ', &
seq_timemgr_alarm_tprof = 'seq_timemgr_alarm_tprof ', &
seq_timemgr_alarm_histavg = 'seq_timemgr_alarm_histavg '
integer(SHR_KIND_IN),private,parameter :: &
seq_timemgr_nalarm_restart = 1, &
seq_timemgr_nalarm_run = 2, &
seq_timemgr_nalarm_stop = 3, &
seq_timemgr_nalarm_datestop= 4, &
seq_timemgr_nalarm_history = 5, &
seq_timemgr_nalarm_atmrun = 6, &
seq_timemgr_nalarm_lndrun = 7, &
seq_timemgr_nalarm_ocnrun = 8, &
seq_timemgr_nalarm_icerun = 9, &
seq_timemgr_nalarm_glcrun =10, &
seq_timemgr_nalarm_ocnnext =11, &
seq_timemgr_nalarm_tprof =12, &
seq_timemgr_nalarm_histavg =13
type EClock_pointer ! needed for array of pointers
type(ESMF_Clock),pointer :: EClock
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 -------------------------------------------------------
! Restart fields - use module data to share values between subroutines in this module
integer, parameter :: nrestvar = 6
character(len=*),parameter :: restname(nrestvar) = &
(/'start_ymd ','start_tod ','ref_ymd ','ref_tod ', &
'curr_ymd ','curr_tod '/)
character(len=*),parameter :: restlnam(nrestvar) = &
(/'clock start date','clock start tod ','clock ref date ','clock ref tod ', &
'clock curr date ','clock curr tod '/)
character(len=*),parameter :: restunit(nrestvar) = &
(/'date [YYYYMMDD] ','seconds ','date [YYYYMMDD] ','seconds ', &
'date [YYYYMMDD] ','seconds '/)
character(len=*),parameter :: resttype(nrestvar) = &
(/'integer ','integer ','integer ','integer ', &
'integer ','integer '/)
integer(SHR_KIND_IN) :: rest_start_ymd ! Start date (YYYYMMDD)
integer(SHR_KIND_IN) :: rest_start_tod ! Start time of day (seconds)
integer(SHR_KIND_IN) :: rest_ref_ymd ! Reference date (YYYYMMDD)
integer(SHR_KIND_IN) :: rest_ref_tod ! Reference time of day (seconds)
integer(SHR_KIND_IN) :: rest_curr_ymd ! Current ymd (YYYYMMDD)
integer(SHR_KIND_IN) :: rest_curr_tod ! Current tod (seconds)
type(ESMF_Calendar), target, save :: seq_timemgr_cal ! calendar
character(len=SHR_KIND_CS),save :: seq_timemgr_calendar ! calendar string
logical :: seq_timemgr_end_restart ! write restarts at end of run?
logical, save :: seq_timemgr_setCalendar = .false. ! if calendar has been set
integer, parameter :: SecPerDay = 86400 ! Seconds per day
!===============================================================================
contains
!===============================================================================
!===============================================================================
! !IROUTINE: seq_timemgr_clockInit -- Initializes clocks
!
! !DESCRIPTION:
!
! Initializes clock
!
! !INTERFACE: ------------------------------------------------------------------
subroutine seq_timemgr_clockInit(SyncClock, nmlfile, restart, restart_file, mpicom, & 1,50
EClock_drv, EClock_atm, EClock_lnd, EClock_ocn, EClock_ice, Eclock_glc)
! !USES:
use shr_string_mod
, only : shr_string_toupper
use shr_file_mod
, only : shr_file_getunit, shr_file_freeunit
use shr_mpi_mod
, only : shr_mpi_bcast
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
!EOP
!----- 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_TimeInterval) :: TimeStep ! Clock time-step
type(ESMF_TimeInterval) :: AlarmInterval ! Alarm interval
type(ESMF_CalendarType) :: esmf_caltype ! local esmf calendar
integer :: rc ! Return code
integer :: n ! index
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) :: 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) :: 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 (YYYYMMDD)
integer(SHR_KIND_IN) :: start_tod ! Start time of day (seconds)
integer(SHR_KIND_IN) :: curr_ymd ! Current ymd (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
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
logical :: end_restart ! Write restart at end of run
integer(SHR_KIND_IN) :: nlUnit ! Namelist unit number
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, &
history_option, history_n, history_ymd, &
histavg_option, histavg_n, histavg_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, &
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
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
history_option = seq_timemgr_optNever
history_n = -1
history_ymd = -1
histavg_option = seq_timemgr_optNever
histavg_n = -1
histavg_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
atm_cpl_offset = 0
lnd_cpl_offset = 0
ice_cpl_offset = 0
ocn_cpl_offset = 0
glc_cpl_offset = 0
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 )
!---------------------------------------------------------------------------
! Read Restart
!---------------------------------------------------------------------------
if (restart) then
call seq_timemgr_clockRestart
('read', SyncClock, restart_file)
start_ymd = rest_start_ymd
start_tod = rest_start_tod
ref_ymd = rest_ref_ymd
ref_tod = rest_ref_tod
curr_ymd = rest_curr_ymd
curr_tod = rest_curr_tod
endif
!---------------------------------------------------------------------------
! Modify namelist as needed
!---------------------------------------------------------------------------
if (lnd_cpl_dt == 0) lnd_cpl_dt = atm_cpl_dt ! Copy atm coupling time into lnd
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 ( 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
stop_ymd = 99990101
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),' 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),' 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,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,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) then
write(logunit,*) trim(subname),' ERROR: aliog _cpl_dt = ', &
atm_cpl_dt, lnd_cpl_dt, ice_cpl_dt, ocn_cpl_dt, glc_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(ocn_cpl_offset) > ocn_cpl_dt) then
write(logunit,*) trim(subname),' ERROR: aliog _cpl_offset = ', &
atm_cpl_offset, lnd_cpl_offset, ice_cpl_offset, ocn_cpl_offset, &
glc_cpl_offset
call shr_sys_abort
( subname//': ERROR coupling intervals invalid' )
end if
! --- Start time date ---------------------------------------------------
if ( (start_ymd < 101) .or. (start_ymd > 99991231)) 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( 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( 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( 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( 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_string_toUpper
(calendar)
seq_timemgr_end_restart = end_restart
! --- Create the new calendar if not already set ------
if ( trim(seq_timemgr_calendar) == seq_timemgr_noLeap ) then
esmf_caltype = ESMF_CAL_NOLEAP
call shr_cal_set
('noleap')
else if ( trim(seq_timemgr_calendar) == seq_timemgr_Gregorian ) then
esmf_caltype = ESMF_CAL_GREGORIAN
call shr_cal_set
('gregorian')
else
write(logunit,*) subname//': unrecognized calendar specified: '// &
trim(seq_timemgr_calendar)
call shr_sys_abort
( subname//'ERROR:: bad calendar for ESMF' )
end if
seq_timemgr_cal = ESMF_CalendarCreate
( name='CCSM_'//seq_timemgr_calendar, &
calendarType=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 CCSM 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
! --- this finds the min of dtime excluding the driver value ---
dtime(seq_timemgr_nclock_drv) = maxval(dtime)
dtime(seq_timemgr_nclock_drv) = minval(dtime)
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
enddo
! --- Initialize clocks and alarms ---
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, &
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, &
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, &
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, &
alarmname = trim(seq_timemgr_alarm_histavg))
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, &
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
call ESMF_ClockSet
(SyncClock%ECP(n)%EClock, StopTime=StopTime2)
else
call ESMF_ClockSet
(SyncClock%ECP(n)%EClock, StopTime=StopTime1)
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
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
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_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))
! --- this is the glcrun alarm (there ^) offset by a -dtime of the driver
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))
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))
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, & 41,21
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
!EOP
!----- 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) :: intyrs ! alarm variable
integer(SHR_KIND_IN) :: intmon ! alarm variable
integer(SHR_KIND_IN) :: intsec ! alarm variable
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 = 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)
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)
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 ) 1,21
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(seq_timemgr_type), intent(INOUT) :: SyncClock ! Advancing clock
!EOP
!----- local -----
character(len=*), parameter :: subname = '(seq_timemgr_clockAdvance) '
integer :: n
type(ESMF_Time) :: drvCT,clkCT
integer :: rc ! Return code
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
! --- turn off all alarms on all clocks ---
do n = 1,max_clocks
call seq_timemgr_alarmSetOff
(SyncClock%ECP(n)%EClock)
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_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 (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, alarmname) 13,66
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_Time) ,optional, intent(IN) :: RefTime ! ref time
character(len=*) ,optional, intent(IN) :: alarmname ! alarm name
!EOP
!----- 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_Time) :: AltAlarm ! Alternate 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)
call ESMF_ClockGet
(EClock, TimeStep=AlarmInterval, 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_optNStep)
call ESMF_ClockGet
(EClock, TimeStep=AlarmInterval, 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_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, & 1,12
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
!EOP
!----- 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) 1,8
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(ESMF_Clock), intent(INOUT) :: EClock ! clock/alarm
character(len=*), intent(IN), optional :: alarmname ! alarmname
!EOP
!----- 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
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, alarmListType=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) 4,8
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(ESMF_Clock), intent(INOUT) :: EClock ! clock/alarm
character(len=*), intent(IN), optional :: alarmname ! alarmname
!EOP
!----- 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
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, alarmListType=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_restartAlarmSetOff -- turn alarm off
!
! !DESCRIPTION:
!
! turn alarm off
!
! !INTERFACE: ------------------------------------------------------------------
subroutine seq_timemgr_restartAlarmSetOff( EClock),1
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(ESMF_Clock) , intent(INOUT) :: EClock ! clock/alarm
!EOP
!----- local -----
character(len=*), parameter :: subname = '(seq_timemgr_restartAlarmSetOff) '
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
call seq_timemgr_AlarmSetOff
(EClock, seq_timemgr_alarm_restart)
end subroutine seq_timemgr_restartAlarmSetOff
!===============================================================================
!===============================================================================
! !IROUTINE: seq_timemgr_runAlarmSetOff -- turn alarm off
!
! !DESCRIPTION:
!
! turn alarm off
!
! !INTERFACE: ------------------------------------------------------------------
subroutine seq_timemgr_runAlarmSetOff( EClock),1
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(ESMF_Clock) , intent(INOUT) :: EClock ! clock/alarm
!EOP
!----- local -----
character(len=*), parameter :: subname = '(seq_timemgr_runAlarmSetOff) '
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
call seq_timemgr_AlarmSetOff
(EClock, seq_timemgr_alarm_run)
end subroutine seq_timemgr_runAlarmSetOff
!===============================================================================
!===============================================================================
! !IROUTINE: seq_timemgr_historyAlarmSetOff -- turn alarm off
!
! !DESCRIPTION:
!
! turn alarm off
!
! !INTERFACE: ------------------------------------------------------------------
subroutine seq_timemgr_historyAlarmSetOff( EClock),1
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(ESMF_Clock) , intent(INOUT) :: EClock ! clock/alarm
!EOP
!----- local -----
character(len=*), parameter :: subname = '(seq_timemgr_historyAlarmSetOff) '
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
call seq_timemgr_AlarmSetOff
(EClock, seq_timemgr_alarm_history)
end subroutine seq_timemgr_historyAlarmSetOff
!===============================================================================
!===============================================================================
! !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) 20,12
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(ESMF_Clock), intent(IN) :: EClock ! clock/alarm
character(len=*), intent(IN) :: alarmname ! which alarm
!EOP
!----- local -----
character(len=*), parameter :: subname = '(seq_timemgr_alarmIsOn) '
character(len=*), parameter :: xalarm = 'unset'
integer :: n
integer :: rc
logical :: found
logical :: set
character(len=64) :: name
type(ESMF_Time) :: ETime1, ETime2
type(ESMF_Alarm),pointer :: EAlarm
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, alarmListType=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
(EAlarm_list(n),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) 4,1
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(ESMF_Clock) , intent(IN) :: EClock ! clock/alarm
!EOP
!----- local -----
integer :: rc
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) 3,1
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(ESMF_Clock) , intent(IN) :: EClock ! clock/alarm
!EOP
!----- 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_runAlarmIsOn -- check if an alarm is ringing
!
! !DESCRIPTION:
!
! check if an alarm is ringing
!
! !INTERFACE: ------------------------------------------------------------------
logical function seq_timemgr_runAlarmIsOn( EClock),1
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(ESMF_Clock) , intent(IN) :: EClock ! clock/alarm
!EOP
!----- local -----
character(len=*), parameter :: subname = '(seq_timemgr_runAlarmIsOn) '
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
seq_timemgr_runAlarmIsOn = &
seq_timemgr_alarmIsOn
(EClock, alarmname=seq_timemgr_alarm_run)
end function seq_timemgr_runAlarmIsOn
!===============================================================================
!===============================================================================
! !IROUTINE: seq_timemgr_historyAlarmIsOn -- check if an alarm is ringing
!
! !DESCRIPTION:
!
! check if an alarm is ringing
!
! !INTERFACE: ------------------------------------------------------------------
logical function seq_timemgr_historyAlarmIsOn( EClock),1
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(ESMF_Clock) , intent(IN) :: EClock ! clock/alarm
!EOP
!----- local -----
integer :: rc
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_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 ) 5,4
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
!EOP
!----- 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 ) 8,7
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
!EOP
!----- 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
if (year < 0) then
ymd = 0
else
call shr_cal_ymd2date
(year,month,day,ymd)
endif
endif
if ( present(tod) ) then
if (year < 0) then
tod = 0
else
tod = sec
endif
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 CCSM clock
!
! !INTERFACE: ------------------------------------------------------------------
subroutine seq_timemgr_EClockInit( TimeStep, StartTime, RefTime, CurrTime, EClock ) 1,9
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
!EOP
!----- 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 = 'CCSM 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
(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) 2,3
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
!EOP
!----- 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_clockRestart -- Read in the clock restart file
!
! !DESCRIPTION:
!
! Read in clock restart information from given input netCDF file into the
! clockNMLinfo object. This sets up the object so that it then can be used
! to initialize a clock object with a time that will correspond to the restart
! file.
!
! !INTERFACE: ------------------------------------------------------------------
subroutine seq_timemgr_clockRestart( type, SyncClock, restart_file, mpicom) 2,36
! !USES:
USE shr_ncio_mod
, ONLY : shr_ncio_descripType, shr_ncio_descripInit, &
shr_ncio_descripSetDefault, &
shr_ncio_open, shr_ncio_close, &
shr_ncio_descripRead, shr_ncio_descripName, &
shr_ncio_descripPutData, shr_ncio_descripWrite, &
shr_ncio_descripGetInteger, &
shr_ncio_descripGetRealR8, &
shr_ncio_descripGetString, &
shr_ncio_descripGetLogical, &
shr_ncio_setDebug
USE shr_string_mod
, ONLY : shr_string_listGetIndexF
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(len=*), intent(IN) :: type ! read or write
type(seq_timemgr_type), intent(INOUT) :: SyncClock! Clock
character(len=*), intent(IN) :: restart_file! Restart local filename
integer, optional, intent(IN) :: mpicom ! MPI communicator
!EOP
!----- local -----
character(len=*), parameter :: subname = '(seq_timemgr_clockRestart) '
integer :: iam ! pe number
logical :: lmaster ! master task
integer :: n ! Index
integer :: ncId ! NetCDF file id
logical :: exists ! If file exists or not
integer(SHR_KIND_IN) :: intvar ! integer variable
real(SHR_KIND_R8) :: real8var ! real8 variable
logical :: logvar ! logical variable
character(SHR_KIND_CL) :: strvar ! string variable
logical :: doread ! convert type to logical
integer :: ierr ! Return code
type(shr_ncio_descripType) :: restvar(nrestvar)
integer(SHR_KIND_IN), parameter :: intFill = -9876
real(SHR_KIND_R8) , parameter :: real8Fill = -9876._SHR_KIND_R8
character(len=*), parameter :: prefix = "seq_timemgr_"
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
if (trim(type) == 'read') then
doread = .true.
elseif (trim(type) == 'write') then
doread = .false.
else
write(logunit,*) subname,' ERROR: invalid type ',trim(type)
call shr_sys_abort
()
endif
iam = 0
if ( present(mpicom) )then
call mpi_comm_rank(mpicom,iam,ierr)
endif
lmaster = .false.
if (iam == 0) lmaster = .true.
!---------------------------------------------------------------------------
! Initialize, required for both Read and Write
!---------------------------------------------------------------------------
call shr_ncio_descripSetDefault
( nrestvar, restvar )
do n = 1, nrestvar
if (trim(resttype(n)) == 'integer') then
call shr_ncio_descripInit
( restvar(n), restname(n), &
LongName = restlnam(n), units = restunit(n), &
IntegerData =.true., IntegerFill = IntFill )
elseif (trim(resttype(n)) == 'real8') then
call shr_ncio_descripInit
( restvar(n), restname(n), &
LongName = restlnam(n), units = restunit(n), &
RealR8Data =.true., RealR8Fill = real8Fill )
elseif (trim(resttype(n)) == 'logical') then
call shr_ncio_descripInit
( restvar(n), restname(n), &
LongName = restlnam(n), units = restunit(n), &
LogicalData =.true. )
elseif (trim(resttype(n)) == 'char') then
call shr_ncio_descripInit
( restvar(n), restname(n), &
LongName = restlnam(n), units = restunit(n), &
StringData =.true. )
else
write(logunit,*) subname,' ERROR descripInit not implemented for type ',trim(resttype(n))
call shr_sys_abort
()
endif
enddo
!---------------------------------------------------------------------------
! Write Begin
!---------------------------------------------------------------------------
if (.not.doread) then
do n = 1, nrestvar
selectcase (trim(restname(n)))
case('start_ymd')
call seq_timemgr_EClockGetData
( SyncClock%ECP(seq_timemgr_nclock_drv)%EClock, start_ymd = intvar )
case('start_tod')
call seq_timemgr_EClockGetData
( SyncClock%ECP(seq_timemgr_nclock_drv)%EClock, start_tod = intvar )
case('ref_ymd')
call seq_timemgr_EClockGetData
( SyncClock%ECP(seq_timemgr_nclock_drv)%EClock, ref_ymd = intvar )
case('ref_tod')
call seq_timemgr_EClockGetData
( SyncClock%ECP(seq_timemgr_nclock_drv)%EClock, ref_tod = intvar )
case('curr_ymd')
call seq_timemgr_EClockGetData
( SyncClock%ECP(seq_timemgr_nclock_drv)%EClock, curr_ymd = intvar )
case('curr_tod')
call seq_timemgr_EClockGetData
( SyncClock%ECP(seq_timemgr_nclock_drv)%EClock, curr_tod = intvar )
case default
write(logunit,*) subname,' ERROR descripPut not implemented for name ',trim(restname(n))
call shr_sys_abort
()
endselect
if (trim(resttype(n)) == 'integer') then
call shr_ncio_descripPutData
( restvar(n), restname(n), IntegerData=intvar )
elseif (trim(resttype(n)) == 'real8') then
call shr_ncio_descripPutData
( restvar(n), restname(n), RealR8Data =real8var )
elseif (trim(resttype(n)) == 'logical') then
call shr_ncio_descripPutData
( restvar(n), restname(n), LogicalData=logvar )
elseif (trim(resttype(n)) == 'char') then
call shr_ncio_descripPutData
( restvar(n), restname(n), StringData =trim(strvar) )
else
write(logunit,*) subname,' ERROR descripPut not implemented for type ',trim(resttype(n))
call shr_sys_abort
()
end if
enddo
call shr_ncio_open
( restart_file, lmaster, FileType=prefix, &
ncId=ncId, exists=exists, writing=.true. )
if ( present(mpicom) )then
call shr_ncio_descripWrite
( ncId, nrestvar, prefix=prefix, mpicom=mpicom, &
mastertask=lmaster, exists=exists, var=restvar )
else
call shr_ncio_descripWrite
( ncId, nrestvar, prefix=prefix, &
exists=exists, var=restvar )
end if
call shr_ncio_close
( ncId, lmaster, type=prefix, NCFileName=restart_file )
endif
!---------------------------------------------------------------------------
! Write End
!---------------------------------------------------------------------------
!---------------------------------------------------------------------------
! Read Begin
!---------------------------------------------------------------------------
if (doread) then
! --- Read in restart file -------
call shr_ncio_open
( restart_file, lmaster, FileType=prefix, &
ncId=ncId, exists=exists, writing=.false. )
if ( present(MPICom) )then
call shr_ncio_descripRead
( ncId, nrestvar, prefix=prefix, mpicom=MPICom, &
mastertask=lmaster, var=restvar )
else
call shr_ncio_descripRead
( ncId, nrestvar, prefix=prefix, &
var=restvar )
end if
call shr_ncio_close
( ncId, lmaster, type=prefix, NCFileName=restart_file )
do n = 1, nrestvar
! --- verify that restvar name is consistent with restname ---
! --- this is a little paranoid given the descripInit call above ---
if (trim(shr_ncio_descripName
(restvar(n))) /= trim(restname(n))) then
write(logunit,*) subname,' ERROR restvar name no match with restname ', &
trim(shr_ncio_descripName
(restvar(n))),' ',trim(restname(n))
call shr_sys_abort
()
endif
if (trim(resttype(n)) == 'integer') then
intvar = shr_ncio_descripGetInteger
(restvar(n))
if (lmaster.and.loglevel > 1) write(logunit) subname,' read ',trim(restname(n)),intvar
elseif (trim(resttype(n)) == 'real8') then
real8var = shr_ncio_descripGetRealR8 (restvar(n))
if (lmaster.and.loglevel > 1) write(logunit) subname,' read ',trim(restname(n)),real8var
elseif (trim(resttype(n)) == 'logical') then
logvar = shr_ncio_descripGetLogical
(restvar(n))
if (lmaster.and.loglevel > 1) write(logunit) subname,' read ',trim(restname(n)),logvar
elseif (trim(resttype(n)) == 'char') then
strvar = shr_ncio_descripGetString (restvar(n))
if (lmaster.and.loglevel > 1) write(logunit) subname,' read ',trim(restname(n)),trim(strvar)
else
write(logunit,*) subname,' ERROR descripGet not implemented for type ',trim(resttype(n))
call shr_sys_abort
()
endif
selectcase (trim(restname(n)))
case('start_ymd')
rest_start_ymd = intvar
case('start_tod')
rest_start_tod = intvar
case('ref_ymd')
rest_ref_ymd = intvar
case('ref_tod')
rest_ref_tod = intvar
case('curr_ymd')
rest_curr_ymd = intvar
case('curr_tod')
rest_curr_tod = intvar
case default
write(logunit,*) subname,' ERROR descripGet not implemented for ',trim(restname(n))
call shr_sys_abort
()
endselect
enddo
endif
end subroutine seq_timemgr_clockRestart
!===============================================================================
!===============================================================================
! !IROUTINE: seq_timemgr_clockPrint -- Print clock information out
!
! !DESCRIPTION:
!
! Print clock information out.
!
! !INTERFACE: ------------------------------------------------------------------
subroutine seq_timemgr_clockPrint( SyncClock ) 1,5
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(seq_timemgr_type), intent(in) :: SyncClock ! Input clock to print
!EOP
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,I8.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, alarmListType=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 ),15
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
!EOP
!----- 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 ) 39,2
! !USES:
implicit none
! !INPUT/OUTPUT PARAMETERS:
integer, intent(in) :: rc ! return code from ESMF
character(len=*),optional,intent(in) :: msg ! error message
!EOP
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