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

📄 time_manager.f90

📁 CCSM Research Tools: Community Atmosphere Model (CAM)
💻 F90
📖 第 1 页 / 共 2 页
字号:
#include <misc.h>#include <preproc.h>module time_manager#if (defined OFFLINE) || (defined COUP_CSM)   use precision, only: r8   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#if (defined SPMD)   use spmdMod, only: mpicom, mpiint, masterproc#else   use spmdMod, only: masterproc#endif   implicit none   private   save! Public methods   public :: &      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 date components of the start date      get_ref_date,             &! return date components of the reference date      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      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 in date calculations ('NO_LEAP' or 'GREGORIAN')   integer, parameter :: uninit_int = -999999999  !This is private to this module   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   ! Private module data   type(esmf_timemgr) :: tm_id          ! time manager ID   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   logical :: first_restart_step = .false.  ! true for first step of a restart or branch run!=========================================================================================contains!=========================================================================================subroutine timemgr_init()! Initialize the ESMF time manager.!! NOTE - This assumes that the namelist variables ! have been set before this routine is called.     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 ( dtime == uninit_int ) then      write(6,*)sub,': dtime must be specified in namelist'      call endrun   end if   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      write(6,*)sub,': start_ymd must be specified in namelist'      call endrun   end if   if ( start_tod == uninit_int ) then      write(6,*)sub,': start_tod must be specified in namelist'      call endrun   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')! 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.!    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   integer :: ier                !error code! Some backwards compatibility stuff:   type(esmf_time) :: diff   integer :: ntspday, ndays, nsecs!-----------------------------------------------------------------------------------------#if ( defined SPMD )    call mpi_bcast(rst_type,      1, mpiint, 0, mpicom, ier)   call mpi_bcast(rst_nstep,     1, mpiint, 0, mpicom, ier)   call mpi_bcast(rst_step_days, 1, mpiint, 0, mpicom, ier)   call mpi_bcast(rst_step_sec,  1, mpiint, 0, mpicom, ier)   call mpi_bcast(rst_start_ymd, 1, mpiint, 0, mpicom, ier)   call mpi_bcast(rst_start_tod, 1, mpiint, 0, mpicom, ier)   call mpi_bcast(rst_stop_ymd,  1, mpiint, 0, mpicom, ier)   call mpi_bcast(rst_stop_tod,  1, mpiint, 0, mpicom, ier)   call mpi_bcast(rst_ref_ymd,   1, mpiint, 0, mpicom, ier)   call mpi_bcast(rst_ref_tod,   1, mpiint, 0, mpicom, ier)   call mpi_bcast(rst_curr_ymd,  1, mpiint, 0, mpicom, ier)   call mpi_bcast(rst_curr_tod,  1, mpiint, 0, mpicom, ier)#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.   start_date = esmf_dateinit(rst_type, rst_start_ymd, rst_start_tod, rc)   call chkrc(rc, sub//': error return from esmf_dateinit: setting start_date')! Initialize current date.   curr_date = esmf_dateinit(rst_type, rst_curr_ymd, rst_curr_tod, rc)   call chkrc(rc, sub//': error return from esmf_dateinit: setting curr_date')! Initialize stop date.   if ( stop_ymd /= uninit_int ) then      stop_date = esmf_dateinit(rst_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(curr_date, dtime*nelapse, rc)      else         stop_date = esmf_dateincrementday(curr_date, -nelapse, rc)      end if   else      stop_date = esmf_dateinit(rst_type, rst_stop_ymd, rst_stop_tod, rc)   end if   call chkrc(rc, sub//': error return setting stop_date')! Check that stop date is later than current date.   call esmf_dateislater(curr_date, stop_date, islater, rc)   call chkrc(rc, sub//': error return from esmf_dateislater: comparing start and stop dates')   if ( .not. islater ) then      write(6,*)sub,': stop date must be specified later than current date: '      call esmf_dateget(curr_date, ymd, tod)      write(6,*)' Current date (ymd tod): ', ymd, tod      call esmf_dateget(stop_date, ymd, tod)      write(6,*)' Stop date (ymd tod): ', ymd, tod      call endrun   end if   call esmf_dateget(stop_date, rst_stop_ymd, rst_stop_tod)! Restart a time manager.   tm_id = esmf_timemgrrestartread(rst_type, rst_nstep, rst_step_days, rst_step_sec, rst_start_ymd, &                                  rst_start_tod, rst_stop_ymd, rst_stop_tod, rst_ref_ymd, rst_ref_tod, &                                  rst_curr_ymd, rst_curr_tod, rc)   call chkrc(rc, sub//': error return from esmf_timemgrrestartread')! Advance the timestep.  Data from the restart file corresponds to the! last timestep of the previous run.   call advance_timestep()!  Set flag that this is the first timestep of the restart run.   first_restart_step = .true.! 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_restart!=========================================================================================subroutine timemgr_print()   implicit none! Local variables   character(len=*), parameter :: sub = 'timemgr_print'   integer :: rc   integer :: day, sec, ymd, tod   character(len=32) :: cal     ! Calendar to use in date calculations.   integer ::&                  ! Data required to restart time manager:        type      = uninit_int,  &! calendar type        nstep     = uninit_int,  &! current step number        step_days = uninit_int,  &! days component of timestep size        step_sec  = uninit_int,  &! seconds component of timestep size        start_ymd = uninit_int,  &! start date        start_tod = uninit_int,  &! start time of day        stop_ymd  = uninit_int,  &! stop date        stop_tod  = uninit_int,  &! stop time of day        ref_ymd   = uninit_int,  &! reference date        ref_tod   = uninit_int,  &! reference time of day        curr_ymd  = uninit_int,  &! current date        curr_tod  = uninit_int    ! current time of day!-----------------------------------------------------------------------------------------   call esmf_timemgrrestartwrite(tm_id, type, nstep, step_days, step_sec, &                                start_ymd, start_tod, stop_ymd, stop_tod, ref_ymd, &                                ref_tod, curr_ymd, curr_tod, rc)   call chkrc(rc, sub//': error return from esmf_timemgrrestartwrite')   write(6,*)' ********** Time Manager Configuration **********'   if ( type == esmf_no_leap ) then      cal = 'NO_LEAP'   else if ( type == esmf_gregorian ) then      cal = 'GREGORIAN'   end if   write(6,*)' Calendar type:            ',trim(cal)   write(6,*)' Timestep size (seconds):  ', (step_days*86400 + step_sec)   write(6,*)' Start date (ymd tod):     ', start_ymd, start_tod   write(6,*)' Stop date (ymd tod):      ', stop_ymd, stop_tod   write(6,*)' Reference date (ymd tod): ', ref_ymd, ref_tod   write(6,*)' Current step number:      ', nstep   write(6,*)' Ending step number:       ', nestep   write(6,*)' Current date (ymd tod):   ', curr_ymd, curr_tod   write(6,*)' ************************************************'end subroutine timemgr_print!=========================================================================================subroutine advance_timestep()! Increment the timestep number.   implicit none   ! Local variables   character(len=*), parameter :: sub = 'advance_timestep'   integer :: rc!-----------------------------------------------------------------------------------------   call esmf_timemgradvance(tm_id, rc)   call chkrc(rc, sub//': error return from esmf_timemgradvance')! Set first step flag off.   first_restart_step = .false.end subroutine advance_timestep!=========================================================================================function get_step_size()! Return the step size in seconds.

⌨️ 快捷键说明

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