!===============================================================================
! SVN $Id: seq_rest_mod.F90 18683 2009-09-30 22:20:22Z kauff $
! SVN $URL: https://svn-ccsm-models.cgd.ucar.edu/drv/seq_mct/branch_tags/cesm1_0_rel_tags/cesm1_0_rel01_drvseq3_1_32/driver/seq_rest_mod.F90 $
!===============================================================================
!BOP ===========================================================================
!
! !MODULE: seq_rest_mod -- cpl7 restart reading/writing routines
!
! !DESCRIPTION:
!
! Reads & writes cpl7 restart files
!
! !REMARKS:
!
! aVect, domain, and fraction info accessed via seq_avdata_mod
! to avoid excessively long routine arg lists.
!
! !REVISION HISTORY:
! 2009-Sep-25 - B. Kauffman - move from cpl7 main program into rest module
! 2007-mmm-dd - T. Craig - initial restart functionality
!
! !INTERFACE: ------------------------------------------------------------------
module seq_rest_mod 1,14
#define NEW_BUDGET
! !USES:
use shr_kind_mod
, only: R8 => SHR_KIND_R8, IN => SHR_KIND_IN
use shr_kind_mod
, only: CL => SHR_KIND_CL, CS => SHR_KIND_CS
use shr_sys_mod
, only: shr_sys_abort, shr_sys_flush
use shr_mpi_mod
, only : shr_mpi_bcast
use shr_cal_mod
, only: shr_cal_date2ymd
use mct_mod
! adds mct_ prefix to mct lib
use ESMF_Mod
use seq_avdata_mod
! drv aVects & associated domain, fract, cdata (public read/write data)
use seq_diag_mct
! diagnostic routines (public read/write data)
use seq_comm_mct
! Sets mpi communicators, logunit and loglevel
use seq_cdata_mod
! "cdata" type & methods (domain + decomp + infodata in one datatype)
use seq_infodata_mod
! "infodata" gathers various control flags into one datatype
use seq_timemgr_mod
! clock & alarm routines
use seq_io_mod
! lower level io routines
implicit none
private
! !PUBLIC TYPES:
! no public types
! !PUBLIC MEMBER FUNCTIONS
public :: seq_rest_read ! read cpl7 restart data
public :: seq_rest_write ! write cpl7 restart data
! !PUBLIC DATA MEMBERS:
! no public data
!EOP
!----------------------------------------------------------------------------
! local data
!----------------------------------------------------------------------------
logical :: iamin_CPLID ! pe associated with CPLID
integer(IN) :: mpicom_GLOID ! MPI global communicator
integer(IN) :: mpicom_CPLID ! MPI cpl communicator
integer(IN) :: nthreads_GLOID ! OMP global number of threads
integer(IN) :: nthreads_CPLID ! OMP cpl number of threads
logical :: drv_threading ! driver threading control
logical :: atm_present ! .true. => atm is present
logical :: lnd_present ! .true. => land is present
logical :: ice_present ! .true. => ice is present
logical :: ocn_present ! .true. => ocn is present
logical :: rof_present ! .true. => land runoff is present
logical :: glc_present ! .true. => glc is present
logical :: sno_present ! .true. => land sno is present
logical :: atm_prognostic ! .true. => atm comp expects input
logical :: lnd_prognostic ! .true. => lnd comp expects input
logical :: ice_prognostic ! .true. => ice comp expects input
logical :: ocn_prognostic ! .true. => ocn comp expects input
logical :: ocnrof_prognostic ! .true. => ocn comp expects runoff input
logical :: glc_prognostic ! .true. => glc comp expects input
logical :: sno_prognostic ! .true. => sno comp expects input
integer(IN) :: info_debug = 0 ! local info_debug level
!===============================================================================
contains
!===============================================================================
subroutine seq_rest_read(rest_file) 1,26
implicit none
character(*),intent(in) :: rest_file ! restart file path/name
integer(IN) :: n,n1,n2,n3
real(r8),allocatable :: ds(:) ! for reshaping diag data for restart file
real(r8),allocatable :: ns(:) ! for reshaping diag data for restart file
character(CS) :: string
integer(IN) :: ierr ! MPI error return
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
!----------------------------------------------------------------------------
! get required infodata
!----------------------------------------------------------------------------
iamin_CPLID = seq_comm_iamin
(CPLID)
call seq_comm_setptrs
(GLOID,mpicom=mpicom_GLOID,nthreads=nthreads_GLOID)
call seq_comm_setptrs
(CPLID,mpicom=mpicom_CPLID,nthreads=nthreads_CPLID)
call seq_infodata_getData
(infodata,drv_threading=drv_threading)
call seq_infodata_getData
(infodata, &
atm_present=atm_present, &
lnd_present=lnd_present, &
rof_present=rof_present, &
ice_present=ice_present, &
ocn_present=ocn_present, &
glc_present=glc_present, &
sno_present=sno_present )
call seq_infodata_getData
(infodata, &
atm_prognostic=atm_prognostic, &
lnd_prognostic=lnd_prognostic, &
ice_prognostic=ice_prognostic, &
ocn_prognostic=ocn_prognostic, &
ocnrof_prognostic=ocnrof_prognostic, &
glc_prognostic=glc_prognostic, &
sno_prognostic=sno_prognostic )
if (iamin_CPLID) then
if (drv_threading) call seq_comm_setnthreads
(nthreads_CPLID)
if (atm_present) then
call seq_io_read
(rest_file,cdata_ax,fractions_ax,'fractions_ax')
call seq_io_read
(rest_file,cdata_ax,a2x_ax,'a2x_ax')
endif
if (lnd_present) then
call seq_io_read
(rest_file,cdata_lx,fractions_lx,'fractions_lx')
call seq_io_read
(rest_file,cdata_lx,l2x_lx,'l2x_lx')
endif
if (ocn_present) then
call seq_io_read
(rest_file,cdata_ox,fractions_ox,'fractions_ox')
call seq_io_read
(rest_file,cdata_ox,o2x_ox,'o2x_ox')
call seq_io_read
(rest_file,cdata_ox,x2oacc_ox%data,'x2oacc_ox')
! call seq_io_read(rest_file,cdata_ox,x2oacc_ox%steps_done,'x2oacc_ox_cnt')
call seq_io_read
(rest_file,cdata_ox,x2oacc_ox_cnt,'x2oacc_ox_cnt')
call seq_io_read
(rest_file,cdata_ox,xao_ox,'xao_ox')
call seq_io_read
(rest_file,cdata_ax,xao_ax,'xao_ax')
endif
if (ice_present) then
call seq_io_read
(rest_file,cdata_ix,fractions_ix,'fractions_ix')
call seq_io_read
(rest_file,cdata_ix,i2x_ix,'i2x_ix')
endif
if (rof_present .and. ocnrof_prognostic) then
call seq_io_read
(rest_file,cdata_rx,r2xacc_rx%data,'r2xacc_rx')
call seq_io_read
(rest_file,cdata_rx,r2xacc_rx_cnt,'r2xacc_rx_cnt')
endif
if (glc_present) then
call seq_io_read
(rest_file,cdata_gx,fractions_gx,'fractions_gx')
endif
if (sno_present) then
call seq_io_read
(rest_file,cdata_sx,x2s_sx,'x2s_sx')
endif
#if (defined NEW_BUDGET)
n = size(budg_dataG)
allocate(ds(n),ns(n))
call seq_io_read
(rest_file,cdata_ax,ds,'budg_dataG')
call seq_io_read
(rest_file,cdata_ax,ns,'budg_ns')
n = 0
do n1 = 1,size(budg_dataG,dim=1)
do n2 = 1,size(budg_dataG,dim=2)
do n3 = 1,size(budg_dataG,dim=3)
n = n + 1
budg_dataG(n1,n2,n3) = ds(n)
budg_ns (n1,n2,n3) = ns(n)
enddo
enddo
enddo
! call shr_mpi_bcast(budg_dataG,cpl_io_root) ! not necessary, io lib does bcast
deallocate(ds,ns)
#endif
if (drv_threading) call seq_comm_setnthreads
(nthreads_GLOID)
endif
end subroutine seq_rest_read
!===============================================================================
subroutine seq_rest_write(EClock_d,seq_SyncClock) 1,37
implicit none
type(ESMF_Clock) ,intent(in) :: EClock_d ! driver clock
type(seq_timemgr_type),intent(inout) :: seq_SyncClock ! contains ptr to driver clock
integer(IN) :: n,n1,n2,n3,fk
integer(IN) :: curr_ymd ! Current date YYYYMMDD
integer(IN) :: curr_tod ! Current time-of-day (s)
integer(IN) :: yy,mm,dd ! year, month, day
character(CL) :: case_name ! case name
logical :: whead,wdata ! flags header/data writing
logical :: cdf64 ! true => create netCDF with 64 bit addressing
character(CL) :: rest_file ! Local path to restart filename
integer(IN) :: ierr ! MPI error return
real(r8),allocatable :: ds(:) ! for reshaping diag data for restart file
real(r8),allocatable :: ns(:) ! for reshaping diag data for restart file
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
!----------------------------------------------------------------------------
! get required infodata
!----------------------------------------------------------------------------
iamin_CPLID = seq_comm_iamin
(CPLID)
call seq_comm_setptrs
(GLOID,mpicom=mpicom_GLOID,nthreads=nthreads_GLOID)
call seq_comm_setptrs
(CPLID,mpicom=mpicom_CPLID,nthreads=nthreads_CPLID)
call seq_infodata_getData
(infodata,drv_threading=drv_threading)
call seq_infodata_getData
(infodata, &
atm_present=atm_present, &
lnd_present=lnd_present, &
rof_present=rof_present, &
ice_present=ice_present, &
ocn_present=ocn_present, &
glc_present=glc_present, &
sno_present=sno_present )
call seq_infodata_getData
(infodata, &
atm_prognostic=atm_prognostic, &
lnd_prognostic=lnd_prognostic, &
ice_prognostic=ice_prognostic, &
ocn_prognostic=ocn_prognostic, &
ocnrof_prognostic=ocnrof_prognostic, &
glc_prognostic=glc_prognostic, &
sno_prognostic=sno_prognostic )
call seq_infodata_getData
(infodata, cpl_cdf64=cdf64 )
! Write out infodata and time manager data to restart file
call seq_infodata_GetData
( infodata, case_name=case_name)
call seq_timemgr_EClockGetData
( EClock_d, curr_ymd=curr_ymd, curr_tod=curr_tod)
call shr_cal_date2ymd
(curr_ymd,yy,mm,dd)
write(rest_file,"(2a,i4.4,a,i2.2,a,i2.2,a,i5.5,a)") &
trim(case_name), '.cpl.r.', yy,'-',mm,'-',dd,'-',curr_tod,'.nc'
call seq_infodata_Restart
('write',infodata ,rest_file,mpicom_cplid)
call mpi_barrier(mpicom_CPLID,ierr)
call seq_timemgr_clockRestart
('write',seq_SyncClock,rest_file,mpicom_cplid)
call mpi_barrier(mpicom_CPLID,ierr)
! Write driver data to restart file
if (iamin_CPLID) then
if (drv_threading) call seq_comm_setnthreads
(nthreads_CPLID)
#if (defined NEW_BUDGET)
! copy budg_dataG into 1d array
n = size(budg_dataG)
allocate(ds(n),ns(n))
call shr_mpi_bcast(budg_dataG,mpicom_CPLID) ! pio requires data on all pe's?
n = 0
do n1 = 1,size(budg_dataG,dim=1)
do n2 = 1,size(budg_dataG,dim=2)
do n3 = 1,size(budg_dataG,dim=3)
n = n + 1
ds(n) = budg_dataG(n1,n2,n3)
ns(n) = budg_ns(n1,n2,n3)
enddo
enddo
enddo
#endif
call seq_io_wopen
(rest_file,cdata_ax,clobber=.false.,cdf64=cdf64)
! loop twice (for perf), first time write header, second time write data
do fk = 1,2
if (fk == 1) then
whead = .true.
wdata = .false.
call seq_io_redef
(rest_file)
elseif (fk == 2) then
whead = .false.
wdata = .true.
call seq_io_enddef
(rest_file)
else
call shr_sys_abort
('driver_write_rstart fk illegal')
end if
#if (defined NEW_BUDGET)
call seq_io_write
(rest_file,cdata_ax,ds,'budg_dataG',whead=whead,wdata=wdata)
call seq_io_write
(rest_file,cdata_ax,ns,'budg_ns',whead=whead,wdata=wdata)
#endif
if (atm_present) then
call seq_io_write
(rest_file,cdata_ax,fractions_ax,'fractions_ax',whead=whead,wdata=wdata)
call seq_io_write
(rest_file,cdata_ax,a2x_ax,'a2x_ax',whead=whead,wdata=wdata)
endif
if (lnd_present) then
call seq_io_write
(rest_file,cdata_lx,fractions_lx,'fractions_lx',whead=whead,wdata=wdata)
call seq_io_write
(rest_file,cdata_lx,l2x_lx,'l2x_lx',whead=whead,wdata=wdata)
endif
if (ocn_present) then
call seq_io_write
(rest_file,cdata_ox,fractions_ox,'fractions_ox',whead=whead,wdata=wdata)
call seq_io_write
(rest_file,cdata_ox,o2x_ox,'o2x_ox',whead=whead,wdata=wdata)
call seq_io_write
(rest_file,cdata_ox,x2oacc_ox%data,'x2oacc_ox',whead=whead,wdata=wdata)
! call seq_io_write(rest_file,cdata_ox,x2oacc_ox%steps_done,'x2oacc_ox_cnt',whead=whead,wdata=wdata)
call seq_io_write
(rest_file,cdata_ox,x2oacc_ox_cnt,'x2oacc_ox_cnt',whead=whead,wdata=wdata)
call seq_io_write
(rest_file,cdata_ox,xao_ox,'xao_ox',whead=whead,wdata=wdata)
call seq_io_write
(rest_file,cdata_ax,xao_ax,'xao_ax',whead=whead,wdata=wdata)
endif
if (ice_present) then
call seq_io_write
(rest_file,cdata_ix,fractions_ix,'fractions_ix',whead=whead,wdata=wdata)
call seq_io_write
(rest_file,cdata_ix,i2x_ix,'i2x_ix',whead=whead,wdata=wdata)
endif
if (rof_present .and. ocnrof_prognostic) then
call seq_io_write
(rest_file,cdata_rx,r2xacc_rx%data,'r2xacc_rx',whead=whead,wdata=wdata)
call seq_io_write
(rest_file,cdata_rx,r2xacc_rx_cnt,'r2xacc_rx_cnt',whead=whead,wdata=wdata)
endif
if (glc_present) then
call seq_io_write
(rest_file,cdata_gx,fractions_gx,'fractions_gx',whead=whead,wdata=wdata)
endif
if (sno_present) then
call seq_io_write
(rest_file,cdata_sx,x2s_sx,'x2s_sx',whead=whead,wdata=wdata)
endif
enddo
call seq_io_close
(rest_file,cdata_ax)
#if (defined NEW_BUDGET)
deallocate(ds,ns)
#endif
if (drv_threading) call seq_comm_setnthreads
(nthreads_GLOID)
endif
end subroutine seq_rest_write
!===============================================================================
end module seq_rest_mod