⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 time_manager.f90

📁 CCSM Research Tools: Community Atmosphere Model (CAM)
💻 F90
📖 第 1 页 / 共 3 页
字号:
#include <misc.h>module time_manager   use precision, only: r8   use pmgrid, only: masterproc   use esmf_timemgmtmod, only: &      esmf_errhandlersettype, esmf_err_return, esmf_errprint, esmf_success, &      esmf_time, esmf_timeinit, esmf_timeget, esmf_timegetdays, &        esmf_timeincrement, esmf_timedecrement, &      esmf_date, esmf_dateinit, esmf_gregorian, esmf_no_leap, esmf_dateget, &        esmf_dateincrementsec, esmf_dateincrementday, esmf_datedecrement, &        esmf_datediff, esmf_dategetfltdayofyear, &      esmf_timemgr, esmf_timemgrinit, esmf_timemgradvance, esmf_timemgrgetnstep, &        esmf_timemgrgetstepsize, esmf_timemgrgetstartdate, esmf_timemgrgetbasedate, &        esmf_timemgrlaststep, esmf_timemgrgetcurrdate, esmf_timemgrgetprevdate, esmf_dateislater, &        esmf_timemgrrestartwrite, esmf_timemgrrestartread   use string_utils, only: to_upper   use dycore, only: dycore_is#ifdef SPMD   use mpishorthand, only: mpicom, mpiint, mpilog#endif   implicit none   private   save! Public methods   public ::&      timemgr_preset,           &! time manager initialization before namelist input      timemgr_init,             &! time manager initialization      advance_timestep,         &! increment timestep number      get_step_size,            &! return step size in seconds      get_nstep,                &! return timestep number      get_curr_date,            &! return date components at end of current timestep      get_prev_date,            &! return date components at beginning of current timestep      get_start_date,           &! return components of the start date      get_ref_date,             &! return components of the reference date      get_perp_date,            &! return components of the perpetual date, and current time of day      get_curr_time,            &! return components of elapsed time since reference date      get_curr_calday,          &! return calendar day at end of current timestep      is_first_step,            &! return true on first step of initial run      is_first_restart_step,    &! return true on first step of restart or branch run      is_end_curr_day,          &! return true on last timestep in current day      is_end_curr_month,        &! return true on last timestep in current month      is_last_step,             &! return true on last timestep      is_perpetual,             &! return true if perpetual calendar is in use      timemgr_write_restart,    &! write info to file needed to restart the time manager      timemgr_read_restart,     &! read info from file needed to restart the time manager      timemgr_restart            ! restart the time manager! Public data for namelist input   character(len=32), public ::&      calendar   = 'NO_LEAP'     ! Calendar to use in date calculations.                                 ! 'NO_LEAP' or 'GREGORIAN'   integer, parameter :: uninit_int = -999999999   integer, public ::&      dtime         = uninit_int,  &! timestep in seconds      nestep        = uninit_int,  &! final timestep (or day if negative) number      nelapse       = uninit_int,  &! number of timesteps (or days if negative) to extend a run      start_ymd     = uninit_int,  &! starting date for run in yearmmdd format      start_tod     = 0,           &! starting time of day for run in seconds      stop_ymd      = uninit_int,  &! stopping date for run in yearmmdd format      stop_tod      = 0,           &! stopping time of day for run in seconds      ref_ymd       = uninit_int,  &! reference date for time coordinate in yearmmdd format      ref_tod       = 0,           &! reference time of day for time coordinate in seconds      perpetual_ymd = uninit_int    ! date used by perpetual calendar   logical, public ::&      perpetual_run = .false.       ! .true. => use a perpetual calendar! Public data for communicating with modules that don't have 'get' methods.   integer, public ::&      ic_ymd  = uninit_int,     &! date of initial conditions in yearmmdd format      ic_tod  = 0                ! time of day of initial conditions in seconds                                 ! ic_ymd, ic_tod set in control/readinitial.F90   logical, public ::&      tm_aqua_planet = .false.   ! flag for aqua-planet simulation! Private module data   type(esmf_timemgr) :: tm_id          ! time manager ID   type(esmf_date)    :: tm_perp_date   ! reference date for perpetual calendar day calc   integer ::&                      ! Data required to restart time manager:      rst_type      = uninit_int,  &! calendar type      rst_nstep     = uninit_int,  &! current step number      rst_step_days = uninit_int,  &! days component of timestep size      rst_step_sec  = uninit_int,  &! seconds component of timestep size      rst_start_ymd = uninit_int,  &! start date      rst_start_tod = uninit_int,  &! start time of day      rst_stop_ymd  = uninit_int,  &! stop date      rst_stop_tod  = uninit_int,  &! stop time of day      rst_ref_ymd   = uninit_int,  &! reference date      rst_ref_tod   = uninit_int,  &! reference time of day      rst_curr_ymd  = uninit_int,  &! current date      rst_curr_tod  = uninit_int,  &! current time of day      rst_perp_ymd  = uninit_int    ! perpetual date   logical ::&      rst_perp_cal  = .false.       ! true when using perpetual calendar   logical :: tm_first_restart_step = .false.  ! true for first step of a restart or branch run   logical :: tm_perp_calendar = .false.       ! true when using perpetual calendar!=========================================================================================contains!=========================================================================================subroutine timemgr_preset()! Initialize variables before namelist input.   implicit none! Local variables   character(len=*), parameter :: sub = 'timemgr_preset'!-----------------------------------------------------------------------------------------   if ( dtime == uninit_int ) then      if (dycore_is ('EUL')) then         dtime  = 1200      else if (dycore_is ('SLD')) then         dtime  = 3600      else if (dycore_is ('LR')) then         dtime  = 3600      else         write(6,*)sub,': need valid dycore to set default DTIME'         call endrun      end if   end ifend subroutine timemgr_preset!=========================================================================================subroutine timemgr_init()! Initialize the ESMF time manager.!! NOTE - Assumptions:!      1) The namelist variables have been set before this routine is called.  (set in control/parse_namelist.F90)!      2) ic_ymd, ic_tod are set before this routine is called.  (set in control/readinitial.F90)   implicit none! Local variables   character(len=*), parameter :: sub = 'timemgr_init'   character(len=len(calendar)) :: cal   integer :: rc                 ! return code   integer :: cal_type           ! calendar type   type(esmf_time) :: step_size   ! timestep size   type(esmf_date) :: start_date  ! start date for run   type(esmf_date) :: stop_date   ! stop date for run   type(esmf_date) :: ref_date    ! reference date for time coordinate! Some backwards compatibility stuff:   type(esmf_time) :: diff   integer :: ntspday, ndays, nsecs   logical :: islater!-----------------------------------------------------------------------------------------! Initialize error handling.   call esmf_errhandlersettype(esmf_err_return)! Initialize calendar type.   cal = to_upper(calendar)   if ( trim(cal) == 'NO_LEAP' ) then      cal_type = esmf_no_leap   else if ( trim(cal) == 'GREGORIAN' ) then      cal_type = esmf_gregorian   else      write(6,*)sub,': unrecognized calendar specified: ',calendar      call endrun   end if! Initialize timestep size.   if ( mod(86400,dtime) /=0 ) then      write(6,*)sub,': timestep must divide evenly into 1 day'      call endrun   end if   step_size = esmf_timeinit(0, dtime, rc)   call chkrc(rc, sub//': error return from esmf_timeinit: setting step_size')! Initialize start date.   if ( start_ymd == uninit_int ) then      start_ymd = ic_ymd      start_tod = ic_tod   end if   start_date = esmf_dateinit(cal_type, start_ymd, start_tod, rc)   call chkrc(rc, sub//': error return from esmf_dateinit: setting start_date')! Initialize reference date for time coordinate.   if ( ref_ymd /= uninit_int ) then      ref_date = esmf_dateinit(cal_type, ref_ymd, ref_tod, rc)   else      ref_date = esmf_dateinit(start_date, rc)   end if   call chkrc(rc, sub//': error return from esmf_dateinit: setting ref_date')! Initialize stop date.   if ( stop_ymd /= uninit_int ) then      stop_date = esmf_dateinit(cal_type, stop_ymd, stop_tod, rc)   else if ( nestep /= uninit_int ) then      if ( nestep >= 0 ) then         stop_date = esmf_dateincrementsec(start_date, dtime*nestep, rc)      else         stop_date = esmf_dateincrementday(start_date, -nestep, rc)      end if   else if ( nelapse /= uninit_int ) then      if ( nelapse >= 0 ) then         stop_date = esmf_dateincrementsec(start_date, dtime*nelapse, rc)      else         stop_date = esmf_dateincrementday(start_date, -nelapse, rc)      end if   else      write(6,*)sub,': Must specify one of stop_ymd, nestep, or nelapse'      call endrun   end if   call chkrc(rc, sub//': error return setting stop_date')! Initialize a time manager.   tm_id = esmf_timemgrinit(step_size, start_date, stop_date, ref_date, rc)   call chkrc(rc, sub//': error return from esmf_timemgrinit')! Initialize date used for perpetual calendar day calculation.   if ( tm_aqua_planet ) then      tm_perp_date = esmf_dateinit(cal_type, 321, 0, rc)      call chkrc(rc, sub//': error return from esmf_dateinit: setting tm_perp_date')      tm_perp_calendar = .true.   else if ( perpetual_run ) then      if ( perpetual_ymd /= uninit_int ) then         tm_perp_date = esmf_dateinit(cal_type, perpetual_ymd, 0, rc)         call chkrc(rc, sub//': error return from esmf_dateinit: setting tm_perp_date')         tm_perp_calendar = .true.      else         tm_perp_date = esmf_dateinit(cal_type, ic_ymd, 0, rc)         call chkrc(rc, sub//': error return from esmf_dateinit: setting tm_perp_date')         tm_perp_calendar = .true.      end if   end if! Set variables from "comtim.h interface" for backwards compatibility.! Calculation of ending timestep number (nestep) assumes a constant stepsize.   ntspday = 86400/dtime   diff = esmf_timeinit()   call esmf_datediff(start_date, stop_date, diff, islater, rc)   call chkrc(rc, sub//': error return from esmf_datediff calculating nestep')   call esmf_timeget(diff, ndays, nsecs, rc)   call chkrc(rc, sub//': error return from esmf_timeget calculating nestep')   nestep = ntspday*ndays + nsecs/dtime   if ( mod(nsecs,dtime) /= 0 ) nestep = nestep + 1! Print configuration summary to log file (stdout).   if (masterproc) then      call timemgr_print()   end ifend subroutine timemgr_init!=========================================================================================subroutine timemgr_restart()! Restart the ESMF time manager.!! NOTE - Assumptions:!      1) The namelist variables have been set before this routine is called.!         (set in control/parse_namelist.F90)!         The stop date is the only thing that can be changed by the user on a restart.!      2) Restart data have been read on the master process before this routine is called.!         (timemgr_read_restart called from control/restart.F90::read_restart)   implicit none! Local variables   character(len=*), parameter :: sub = 'timemgr_restart'   integer :: rc                 ! return code   type(esmf_date) :: start_date  ! start date for run   type(esmf_date) :: stop_date   ! stop date for run   type(esmf_date) :: curr_date   ! date of data in restart file   logical :: islater   integer :: ymd, tod! Some backwards compatibility stuff:   type(esmf_time) :: diff   integer :: ntspday, ndays, nsecs!-----------------------------------------------------------------------------------------#if ( defined SPMD )    call mpibcast(rst_type,      1, mpiint, 0, mpicom)   call mpibcast(rst_nstep,     1, mpiint, 0, mpicom)   call mpibcast(rst_step_days, 1, mpiint, 0, mpicom)   call mpibcast(rst_step_sec,  1, mpiint, 0, mpicom)   call mpibcast(rst_start_ymd, 1, mpiint, 0, mpicom)   call mpibcast(rst_start_tod, 1, mpiint, 0, mpicom)   call mpibcast(rst_stop_ymd,  1, mpiint, 0, mpicom)   call mpibcast(rst_stop_tod,  1, mpiint, 0, mpicom)   call mpibcast(rst_ref_ymd,   1, mpiint, 0, mpicom)   call mpibcast(rst_ref_tod,   1, mpiint, 0, mpicom)   call mpibcast(rst_curr_ymd,  1, mpiint, 0, mpicom)   call mpibcast(rst_curr_tod,  1, mpiint, 0, mpicom)   call mpibcast(rst_perp_ymd,  1, mpiint, 0, mpicom)   call mpibcast(rst_perp_cal,  1, mpilog, 0, mpicom)#endif! Initialize error handling.   call esmf_errhandlersettype(esmf_err_return)! Initialize calendar type.   if ( rst_type == esmf_no_leap ) then      calendar = 'NO_LEAP'   else if ( rst_type == esmf_gregorian ) then      calendar = 'GREGORIAN'   else      write(6,*)sub,': unrecognized calendar type in restart file: ',rst_type      call endrun   end if! Initialize the timestep.   dtime = rst_step_days*86400 + rst_step_sec! Initialize start date.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -