!===============================================================================
! SVN $Id: seq_hist_mod.F90 20124 2010-01-01 22:57:57Z tcraig $
! 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_hist_mod.F90 $
!===============================================================================
!BOP ===========================================================================
!
! !MODULE: seq_hist_mod -- cpl7 history writing routines
!
! !DESCRIPTION:
!
! Creates cpl7 history files, instantanious, time-avg, and auxilliary
!
! !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 hist module
! 2009-mmm-dd - T. Craig - initial versions
!
! !INTERFACE: ------------------------------------------------------------------
module seq_hist_mod 1,11
! !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_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, fraction, cdata
use seq_comm_mct
! mpi comm data & routines, plus 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_hist_write ! write instantaneous hist file
public :: seq_hist_writeavg ! write time-avg hist file
public :: seq_hist_writeaux ! write auxiliary hist files
! !PUBLIC DATA MEMBERS:
! no public data
!EOP
!----------------------------------------------------------------------------
! local/module 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
logical :: cdf64 ! true => use 64 bit addressing in netCDF files
!--- domain equivalent 2d grid size ---
integer(IN) :: atm_nx, atm_ny ! nx,ny of 2d grid, if known
integer(IN) :: lnd_nx, lnd_ny ! nx,ny of 2d grid, if known
integer(IN) :: ice_nx, ice_ny ! nx,ny of 2d grid, if known
integer(IN) :: ocn_nx, ocn_ny ! nx,ny of 2d grid, if known
integer(IN) :: rof_nx, rof_ny ! nx,ny of 2d grid, if known
integer(IN) :: glc_nx, glc_ny ! nx,ny of 2d grid, if known
integer(IN) :: sno_nx, sno_ny ! nx,ny of 2d grid, if known
integer(IN) :: info_debug = 0 ! local info_debug level
!===============================================================================
contains
!===============================================================================
subroutine seq_hist_write(EClock_d) 2,51
implicit none
type (ESMF_Clock),intent(in) :: EClock_d ! driver clock
integer(IN) :: curr_ymd ! Current date YYYYMMDD
integer(IN) :: curr_tod ! Current time-of-day (s)
integer(IN) :: start_ymd ! Starting date YYYYMMDD
integer(IN) :: start_tod ! Starting time-of-day (s)
real(r8) :: curr_time ! Time interval since reference time
integer(IN) :: yy,mm,dd ! year, month, day
integer(IN) :: fk ! index
character(CL) :: time_units ! units of time variable
character(CL) :: calendar ! calendar type
character(CL) :: case_name ! case name
character(CL) :: hist_file ! Local path to history filename
integer(IN) :: lsize ! local size of an aVect
logical :: whead,wdata ! for writing restart/history cdf files
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
!----------------------------------------------------------------------------
! 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, &
atm_nx=atm_nx, atm_ny=atm_ny, &
lnd_nx=lnd_nx, lnd_ny=lnd_ny, &
rof_nx=rof_nx, rof_ny=rof_ny, &
ice_nx=ice_nx, ice_ny=ice_ny, &
glc_nx=glc_nx, glc_ny=glc_ny, &
sno_nx=sno_nx, sno_ny=sno_ny, &
ocn_nx=ocn_nx, ocn_ny=ocn_ny )
call seq_infodata_getData
(infodata, cpl_cdf64=cdf64 )
!--- Get current date from clock needed to label the history pointer file ---
call seq_infodata_GetData
( infodata, case_name=case_name)
call seq_timemgr_EClockGetData
( EClock_d, curr_ymd=curr_ymd, curr_tod=curr_tod, &
start_ymd=start_ymd, start_tod=start_tod, curr_time=curr_time, &
calendar=calendar)
call shr_cal_date2ymd
(curr_ymd,yy,mm,dd)
write(hist_file,"(2a,i4.4,a,i2.2,a,i2.2,a,i5.5,a)") &
trim(case_name), '.cpl.hi.', yy,'-',mm,'-',dd,'-',curr_tod,'.nc'
time_units = 'days since ' &
// seq_io_date2yyyymmdd
(start_ymd) // ' ' // seq_io_sec2hms
(start_tod)
if (iamin_CPLID) then
if (drv_threading) call seq_comm_setnthreads
(nthreads_CPLID)
call seq_io_wopen
(hist_file,cdata_ax,clobber=.true.,cdf64=cdf64)
! loop twice, first time write header, second time write data for perf
do fk = 1,2
if (fk == 1) then
whead = .true.
wdata = .false.
elseif (fk == 2) then
whead = .false.
wdata = .true.
call seq_io_enddef
(hist_file)
else
call shr_sys_abort
('seq_hist_write fk illegal')
end if
call seq_io_write
(hist_file,&
time_units=time_units,time_cal=calendar,time_val=curr_time,&
whead=whead,wdata=wdata)
if (atm_present) then
call seq_io_write
(hist_file,cdata_ax,dom_ax%data,'dom_ax', &
nx=atm_nx,ny=atm_ny,whead=whead,wdata=wdata,pre='doma')
call seq_io_write
(hist_file,cdata_ax,fractions_ax,'fractions_ax', &
nx=atm_nx,ny=atm_ny,whead=whead,wdata=wdata,pre='fraca')
call seq_io_write
(hist_file,cdata_ax,x2a_ax,'x2a_ax', &
nx=atm_nx,ny=atm_ny,whead=whead,wdata=wdata,pre='x2a')
call seq_io_write
(hist_file,cdata_ax,a2x_ax,'a2x_ax', &
nx=atm_nx,ny=atm_ny,whead=whead,wdata=wdata,pre='a2x')
! call seq_io_write(hist_file,cdata_ax,l2x_ax,'l2x_ax', &
! nx=atm_nx,ny=atm_ny,whead=whead,wdata=wdata,pre='l2x_ax')
! call seq_io_write(hist_file,cdata_ax,o2x_ax,'o2x_ax', &
! nx=atm_nx,ny=atm_ny,whead=whead,wdata=wdata,pre='o2x_ax')
! call seq_io_write(hist_file,cdata_ax,i2x_ax,'i2x_ax', &
! nx=atm_nx,ny=atm_ny,whead=whead,wdata=wdata,pre='i2x_ax')
endif
if (lnd_present) then
call seq_io_write
(hist_file,cdata_lx,dom_lx%data,'dom_lx', &
nx=lnd_nx,ny=lnd_ny,whead=whead,wdata=wdata,pre='doml')
call seq_io_write
(hist_file,cdata_lx,fractions_lx,'fractions_lx', &
nx=lnd_nx,ny=lnd_ny,whead=whead,wdata=wdata,pre='fracl')
call seq_io_write
(hist_file,cdata_lx,l2x_lx,'l2x_lx', &
nx=lnd_nx,ny=lnd_ny,whead=whead,wdata=wdata,pre='l2x')
call seq_io_write
(hist_file,cdata_lx,x2l_lx,'x2l_lx', &
nx=lnd_nx,ny=lnd_ny,whead=whead,wdata=wdata,pre='x2l')
endif
if (rof_present) then
call seq_io_write
(hist_file,cdata_rx,dom_rx%data,'dom_rx', &
nx=rof_nx,ny=rof_ny,whead=whead,wdata=wdata,pre='domr')
call seq_io_write
(hist_file,cdata_rx,r2x_rx,'r2x_rx', &
nx=rof_nx,ny=rof_ny,whead=whead,wdata=wdata,pre='r2x')
endif
if (rof_present .and. ocnrof_prognostic) then
call seq_io_write
(hist_file,cdata_rx,r2xacc_rx%data,'r2xacc_rx', &
nx=rof_nx,ny=rof_ny,whead=whead,wdata=wdata,pre='r2xacc')
call seq_io_write
(hist_file,cdata_ox,r2x_ox,'r2x_ox', &
nx=ocn_nx,ny=ocn_ny,whead=whead,wdata=wdata,pre='r2xo')
endif
if (ocn_present) then
call seq_io_write
(hist_file,cdata_ox,dom_ox%data,'dom_ox', &
nx=ocn_nx,ny=ocn_ny,whead=whead,wdata=wdata,pre='domo')
call seq_io_write
(hist_file,cdata_ox,fractions_ox,'fractions_ox', &
nx=ocn_nx,ny=ocn_ny,whead=whead,wdata=wdata,pre='fraco')
call seq_io_write
(hist_file,cdata_ox,o2x_ox,'o2x_ox', &
nx=ocn_nx,ny=ocn_ny,whead=whead,wdata=wdata,pre='o2x')
call seq_io_write
(hist_file,cdata_ax,o2x_ax,'o2x_ax', &
nx=atm_nx,ny=atm_ny,whead=whead,wdata=wdata,pre='o2xa')
! call seq_io_write(hist_file,cdata_ox,x2o_ox,'x2o_ox', &
! nx=ocn_nx,ny=ocn_ny,whead=whead,wdata=wdata,pre='x2o')
call seq_io_write
(hist_file,cdata_ox,x2oacc_ox%data,'x2oacc_ox', &
nx=ocn_nx,ny=ocn_ny,whead=whead,wdata=wdata,pre='x2oacc')
! call seq_io_write(hist_file,cdata_ox,x2oacc_ox%steps_done,'x2oacc_ox_cnt', &
! whead=whead,wdata=wdata)
call seq_io_write
(hist_file,cdata_ox,x2oacc_ox_cnt,'x2oacc_ox_cnt', &
whead=whead,wdata=wdata)
call seq_io_write
(hist_file,cdata_ox,xao_ox,'xao_ox', &
nx=ocn_nx,ny=ocn_ny,whead=whead,wdata=wdata,pre='xaoo')
call seq_io_write
(hist_file,cdata_ax,xao_ax,'xao_ax', &
nx=atm_nx,ny=atm_ny,whead=whead,wdata=wdata,pre='xaoa')
endif
if (ice_present) then
call seq_io_write
(hist_file,cdata_ix,dom_ix%data,'dom_ix', &
nx=ice_nx,ny=ice_ny,whead=whead,wdata=wdata,pre='domi')
call seq_io_write
(hist_file,cdata_ix,fractions_ix,'fractions_ix', &
nx=ice_nx,ny=ice_ny,whead=whead,wdata=wdata,pre='fraci')
call seq_io_write
(hist_file,cdata_ix,i2x_ix,'i2x_ix', &
nx=ice_nx,ny=ice_ny,whead=whead,wdata=wdata,pre='i2x')
call seq_io_write
(hist_file,cdata_ix,x2i_ix,'x2i_ix', &
nx=ice_nx,ny=ice_ny,whead=whead,wdata=wdata,pre='x2i')
endif
if (glc_present) then
call seq_io_write
(hist_file,cdata_gx,dom_gx%data,'dom_gx', &
nx=glc_nx,ny=glc_ny,whead=whead,wdata=wdata,pre='domg')
call seq_io_write
(hist_file,cdata_gx,fractions_gx,'fractions_gx', &
nx=glc_nx,ny=glc_ny,whead=whead,wdata=wdata,pre='fracg')
call seq_io_write
(hist_file,cdata_gx,g2x_gx,'g2x_gx', &
nx=glc_nx,ny=glc_ny,whead=whead,wdata=wdata,pre='g2x')
call seq_io_write
(hist_file,cdata_gx,x2g_gx,'x2g_gx', &
nx=glc_nx,ny=glc_ny,whead=whead,wdata=wdata,pre='x2g')
endif
if (sno_present) then
call seq_io_write
(hist_file,cdata_sx,dom_sx%data,'dom_sx', &
nx=sno_nx,ny=sno_ny,whead=whead,wdata=wdata,pre='doms')
call seq_io_write
(hist_file,cdata_sx,s2x_sx,'s2x_sx', &
nx=sno_nx,ny=sno_ny,whead=whead,wdata=wdata,pre='s2x')
call seq_io_write
(hist_file,cdata_sx,x2s_sx,'x2s_sx', &
nx=sno_nx,ny=sno_ny,whead=whead,wdata=wdata,pre='x2s')
endif
enddo
call seq_io_close
(hist_file,cdata_ax)
if (drv_threading) call seq_comm_setnthreads
(nthreads_GLOID)
endif
end subroutine seq_hist_write
!===============================================================================
subroutine seq_hist_writeavg(EClock_d,write_now) 1,44
implicit none
type (ESMF_Clock),intent(in) :: EClock_d ! driver clock
logical ,intent(in) :: write_now ! write or accumulate
integer(IN) :: curr_ymd ! Current date YYYYMMDD
integer(IN) :: curr_tod ! Current time-of-day (s)
integer(IN) :: prev_ymd ! Previous date YYYYMMDD
integer(IN) :: prev_tod ! Previous time-of-day (s)
integer(IN) :: start_ymd ! Starting date YYYYMMDD
integer(IN) :: start_tod ! Starting time-of-day (s)
real(r8) :: curr_time ! Time interval since reference time
real(r8) :: prev_time ! Time interval since reference time
integer(IN) :: yy,mm,dd ! year, month, day
integer(IN) :: fk ! index
character(CL) :: time_units ! units of time variable
character(CL) :: calendar ! calendar type
integer(IN) :: lsize ! local size of an aVect
character(CL) :: case_name ! case name
character(CL) :: hist_file ! Local path to history filename
logical :: whead,wdata ! flags write header vs. data
type(mct_aVect),save :: a2x_ax_avg ! tavg aVect/bundle
type(mct_aVect),save :: x2a_ax_avg
type(mct_aVect),save :: l2x_lx_avg
type(mct_aVect),save :: x2l_lx_avg
type(mct_aVect),save :: r2x_rx_avg
type(mct_aVect),save :: o2x_ox_avg
type(mct_aVect),save :: x2o_ox_avg
type(mct_aVect),save :: i2x_ix_avg
type(mct_aVect),save :: x2i_ix_avg
type(mct_aVect),save :: g2x_gx_avg
type(mct_aVect),save :: x2g_gx_avg
type(mct_aVect),save :: s2x_sx_avg
type(mct_aVect),save :: x2s_sx_avg
integer(IN) ,save :: cnt ! counts samples in tavg
real(r8) ,save :: tbnds(2) ! CF1.0 time bounds
logical ,save :: first_call = .true. ! flags 1st call of this routine
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
!----------------------------------------------------------------------------
! 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, &
atm_nx=atm_nx, atm_ny=atm_ny, &
lnd_nx=lnd_nx, lnd_ny=lnd_ny, &
rof_nx=rof_nx, rof_ny=rof_ny, &
ice_nx=ice_nx, ice_ny=ice_ny, &
glc_nx=glc_nx, glc_ny=glc_ny, &
sno_nx=sno_nx, sno_ny=sno_ny, &
ocn_nx=ocn_nx, ocn_ny=ocn_ny )
call seq_infodata_getData
(infodata, cpl_cdf64=cdf64 )
! Get current date from clock needed to label the histavg pointer file
call seq_timemgr_EClockGetData
( EClock_d, curr_ymd=curr_ymd, curr_tod=curr_tod, &
start_ymd=start_ymd, start_tod=start_tod, curr_time=curr_time, prev_time=prev_time, &
calendar=calendar)
if (first_call) then
if (atm_present) then
lsize = mct_aVect_lsize(a2x_ax)
call mct_aVect_init(a2x_ax_avg,a2x_ax,lsize)
call mct_aVect_zero(a2x_ax_avg)
lsize = mct_aVect_lsize(x2a_ax)
call mct_aVect_init(x2a_ax_avg,x2a_ax,lsize)
call mct_aVect_zero(x2a_ax_avg)
endif
if (lnd_present) then
lsize = mct_aVect_lsize(l2x_lx)
call mct_aVect_init(l2x_lx_avg,l2x_lx,lsize)
call mct_aVect_zero(l2x_lx_avg)
lsize = mct_aVect_lsize(x2l_lx)
call mct_aVect_init(x2l_lx_avg,x2l_lx,lsize)
call mct_aVect_zero(x2l_lx_avg)
endif
if (rof_present .and. ocnrof_prognostic) then
lsize = mct_aVect_lsize(r2x_rx)
call mct_aVect_init(r2x_rx_avg,r2x_rx,lsize)
call mct_aVect_zero(r2x_rx_avg)
endif
if (ocn_present) then
lsize = mct_aVect_lsize(o2x_ox)
call mct_aVect_init(o2x_ox_avg,o2x_ox,lsize)
call mct_aVect_zero(o2x_ox_avg)
lsize = mct_aVect_lsize(x2o_ox)
call mct_aVect_init(x2o_ox_avg,x2o_ox,lsize)
call mct_aVect_zero(x2o_ox_avg)
endif
if (ice_present) then
lsize = mct_aVect_lsize(i2x_ix)
call mct_aVect_init(i2x_ix_avg,i2x_ix,lsize)
call mct_aVect_zero(i2x_ix_avg)
lsize = mct_aVect_lsize(x2i_ix)
call mct_aVect_init(x2i_ix_avg,x2i_ix,lsize)
call mct_aVect_zero(x2i_ix_avg)
endif
if (glc_present) then
lsize = mct_aVect_lsize(g2x_gx)
call mct_aVect_init(g2x_gx_avg,g2x_gx,lsize)
call mct_aVect_zero(g2x_gx_avg)
lsize = mct_aVect_lsize(x2g_gx)
call mct_aVect_init(x2g_gx_avg,x2g_gx,lsize)
call mct_aVect_zero(x2g_gx_avg)
endif
if (sno_present) then
lsize = mct_aVect_lsize(s2x_sx)
call mct_aVect_init(s2x_sx_avg,s2x_sx,lsize)
call mct_aVect_zero(s2x_sx_avg)
lsize = mct_aVect_lsize(x2s_sx)
call mct_aVect_init(x2s_sx_avg,x2s_sx,lsize)
call mct_aVect_zero(x2s_sx_avg)
endif
cnt = 0
tbnds(1) = prev_time
first_call = .false.
endif
if (.not.write_now) then
cnt = cnt + 1
if (atm_present) then
a2x_ax_avg%rAttr = a2x_ax_avg%rAttr + a2x_ax%rAttr
x2a_ax_avg%rAttr = x2a_ax_avg%rAttr + x2a_ax%rAttr
endif
if (lnd_present) then
l2x_lx_avg%rAttr = l2x_lx_avg%rAttr + l2x_lx%rAttr
x2l_lx_avg%rAttr = x2l_lx_avg%rAttr + x2l_lx%rAttr
endif
if (rof_present .and. ocnrof_prognostic) then
r2x_rx_avg%rAttr = r2x_rx_avg%rAttr + r2x_rx%rAttr
endif
if (ocn_present) then
o2x_ox_avg%rAttr = o2x_ox_avg%rAttr + o2x_ox%rAttr
x2o_ox_avg%rAttr = x2o_ox_avg%rAttr + x2o_ox%rAttr
endif
if (ice_present) then
i2x_ix_avg%rAttr = i2x_ix_avg%rAttr + i2x_ix%rAttr
x2i_ix_avg%rAttr = x2i_ix_avg%rAttr + x2i_ix%rAttr
endif
if (glc_present) then
g2x_gx_avg%rAttr = g2x_gx_avg%rAttr + g2x_gx%rAttr
x2g_gx_avg%rAttr = x2g_gx_avg%rAttr + x2g_gx%rAttr
endif
if (sno_present) then
s2x_sx_avg%rAttr = s2x_sx_avg%rAttr + s2x_sx%rAttr
x2s_sx_avg%rAttr = x2s_sx_avg%rAttr + x2s_sx%rAttr
endif
else
cnt = cnt + 1
tbnds(2) = curr_time
if (atm_present) then
a2x_ax_avg%rAttr = (a2x_ax_avg%rAttr + a2x_ax%rAttr) / (cnt * 1.0_r8)
x2a_ax_avg%rAttr = (x2a_ax_avg%rAttr + x2a_ax%rAttr) / (cnt * 1.0_r8)
endif
if (lnd_present) then
l2x_lx_avg%rAttr = (l2x_lx_avg%rAttr + l2x_lx%rAttr) / (cnt * 1.0_r8)
x2l_lx_avg%rAttr = (x2l_lx_avg%rAttr + x2l_lx%rAttr) / (cnt * 1.0_r8)
endif
if (rof_present .and. ocnrof_prognostic) then
r2x_rx_avg%rAttr = (r2x_rx_avg%rAttr + r2x_rx%rAttr) / (cnt * 1.0_r8)
endif
if (ocn_present) then
o2x_ox_avg%rAttr = (o2x_ox_avg%rAttr + o2x_ox%rAttr) / (cnt * 1.0_r8)
x2o_ox_avg%rAttr = (x2o_ox_avg%rAttr + x2o_ox%rAttr) / (cnt * 1.0_r8)
endif
if (ice_present) then
i2x_ix_avg%rAttr = (i2x_ix_avg%rAttr + i2x_ix%rAttr) / (cnt * 1.0_r8)
x2i_ix_avg%rAttr = (x2i_ix_avg%rAttr + x2i_ix%rAttr) / (cnt * 1.0_r8)
endif
if (glc_present) then
g2x_gx_avg%rAttr = (g2x_gx_avg%rAttr + g2x_gx%rAttr) / (cnt * 1.0_r8)
x2g_gx_avg%rAttr = (x2g_gx_avg%rAttr + x2g_gx%rAttr) / (cnt * 1.0_r8)
endif
if (sno_present) then
s2x_sx_avg%rAttr = (s2x_sx_avg%rAttr + s2x_sx%rAttr) / (cnt * 1.0_r8)
x2s_sx_avg%rAttr = (x2s_sx_avg%rAttr + x2s_sx%rAttr) / (cnt * 1.0_r8)
endif
call seq_infodata_GetData
( infodata, case_name=case_name)
call seq_timemgr_EClockGetData
( EClock_d, prev_ymd=prev_ymd, prev_tod=prev_tod)
if (seq_timemgr_histavg_type == seq_timemgr_type_nyear) then
call shr_cal_date2ymd
(prev_ymd,yy,mm,dd)
write(hist_file,"(2a,i4.4,a)") &
trim(case_name), '.cpl.ha.', yy,'.nc'
elseif (seq_timemgr_histavg_type == seq_timemgr_type_nmonth) then
call shr_cal_date2ymd
(prev_ymd,yy,mm,dd)
write(hist_file,"(2a,i4.4,a,i2.2,a)") &
trim(case_name), '.cpl.ha.', yy,'-',mm,'.nc'
elseif (seq_timemgr_histavg_type == seq_timemgr_type_nday) then
call shr_cal_date2ymd
(prev_ymd,yy,mm,dd)
write(hist_file,"(2a,i4.4,a,i2.2,a,i2.2,a)") &
trim(case_name), '.cpl.ha.', yy,'-',mm,'-',dd,'.nc'
else
call shr_cal_date2ymd
(curr_ymd,yy,mm,dd)
write(hist_file,"(2a,i4.4,a,i2.2,a,i2.2,a,i5.5,a)") &
trim(case_name), '.cpl.ha.', yy,'-',mm,'-',dd,'-',curr_tod,'.nc'
endif
time_units = 'days since ' &
// seq_io_date2yyyymmdd
(start_ymd) // ' ' // seq_io_sec2hms
(start_tod)
if (iamin_CPLID) then
if (drv_threading) call seq_comm_setnthreads
(nthreads_CPLID)
call seq_io_wopen
(hist_file,cdata_ax,clobber=.true.,cdf64=cdf64)
! loop twice, first time write header, second time write data for perf
do fk = 1,2
if (fk == 1) then
whead = .true.
wdata = .false.
elseif (fk == 2) then
whead = .false.
wdata = .true.
call seq_io_enddef
(hist_file)
else
call shr_sys_abort
('seq_hist_writeavg fk illegal')
end if
call seq_io_write
(hist_file,&
time_units=time_units,time_cal=calendar,time_val=curr_time,&
whead=whead,wdata=wdata,tbnds=tbnds)
if (atm_present) then
call seq_io_write
(hist_file,cdata_ax,dom_ax%data,'dom_ax', &
nx=atm_nx,ny=atm_ny,whead=whead,wdata=wdata,pre='doma')
call seq_io_write
(hist_file,cdata_ax,x2a_ax_avg,'x2a_ax', &
nx=atm_nx,ny=atm_ny,whead=whead,wdata=wdata,pre='x2aavg',tavg=.true.)
call seq_io_write
(hist_file,cdata_ax,a2x_ax_avg,'a2x_ax', &
nx=atm_nx,ny=atm_ny,whead=whead,wdata=wdata,pre='a2xavg',tavg=.true.)
endif
if (lnd_present) then
call seq_io_write
(hist_file,cdata_lx,dom_lx%data,'dom_lx', &
nx=lnd_nx,ny=lnd_ny,whead=whead,wdata=wdata,pre='doml')
call seq_io_write
(hist_file,cdata_lx,l2x_lx_avg,'l2x_lx', &
nx=lnd_nx,ny=lnd_ny,whead=whead,wdata=wdata,pre='l2xavg',tavg=.true.)
call seq_io_write
(hist_file,cdata_lx,x2l_lx_avg,'x2l_lx', &
nx=lnd_nx,ny=lnd_ny,whead=whead,wdata=wdata,pre='x2lavg',tavg=.true.)
endif
if (rof_present .and. ocnrof_prognostic) then
call seq_io_write
(hist_file,cdata_rx,dom_rx%data,'dom_rx', &
nx=rof_nx,ny=rof_ny,whead=whead,wdata=wdata,pre='domr')
call seq_io_write
(hist_file,cdata_rx,r2x_rx_avg,'r2x_rx', &
nx=rof_nx,ny=rof_ny,whead=whead,wdata=wdata,pre='r2xavg',tavg=.true.)
endif
if (ocn_present) then
call seq_io_write
(hist_file,cdata_ox,dom_ox%data,'dom_ox', &
nx=ocn_nx,ny=ocn_ny,whead=whead,wdata=wdata,pre='domo')
call seq_io_write
(hist_file,cdata_ox,o2x_ox_avg,'o2x_ox', &
nx=ocn_nx,ny=ocn_ny,whead=whead,wdata=wdata,pre='o2xavg',tavg=.true.)
call seq_io_write
(hist_file,cdata_ox,x2o_ox_avg,'x2o_ox', &
nx=ocn_nx,ny=ocn_ny,whead=whead,wdata=wdata,pre='x2oavg',tavg=.true.)
endif
if (ice_present) then
call seq_io_write
(hist_file,cdata_ix,dom_ix%data,'dom_ix', &
nx=ice_nx,ny=ice_ny,whead=whead,wdata=wdata,pre='domi')
call seq_io_write
(hist_file,cdata_ix,i2x_ix_avg,'i2x_ix', &
nx=ice_nx,ny=ice_ny,whead=whead,wdata=wdata,pre='i2xavg',tavg=.true.)
call seq_io_write
(hist_file,cdata_ix,x2i_ix_avg,'x2i_ix', &
nx=ice_nx,ny=ice_ny,whead=whead,wdata=wdata,pre='x2iavg',tavg=.true.)
endif
if (glc_present) then
call seq_io_write
(hist_file,cdata_gx,dom_gx%data,'dom_gx', &
nx=glc_nx,ny=glc_ny,whead=whead,wdata=wdata,pre='domg')
call seq_io_write
(hist_file,cdata_gx,g2x_gx_avg,'g2x_gx', &
nx=glc_nx,ny=glc_ny,whead=whead,wdata=wdata,pre='g2xavg',tavg=.true.)
call seq_io_write
(hist_file,cdata_gx,x2g_gx_avg,'x2g_gx', &
nx=glc_nx,ny=glc_ny,whead=whead,wdata=wdata,pre='x2gavg',tavg=.true.)
endif
if (sno_present) then
call seq_io_write
(hist_file,cdata_sx,dom_sx%data,'dom_sx', &
nx=sno_nx,ny=sno_ny,whead=whead,wdata=wdata,pre='doms')
call seq_io_write
(hist_file,cdata_sx,s2x_sx_avg,'s2x_sx', &
nx=sno_nx,ny=sno_ny,whead=whead,wdata=wdata,pre='s2xavg',tavg=.true.)
call seq_io_write
(hist_file,cdata_sx,x2s_sx_avg,'x2s_sx', &
nx=sno_nx,ny=sno_ny,whead=whead,wdata=wdata,pre='x2savg',tavg=.true.)
endif
enddo
call seq_io_close
(hist_file,cdata_ax)
if (drv_threading) call seq_comm_setnthreads
(nthreads_GLOID)
if (atm_present) then
call mct_aVect_zero(a2x_ax_avg)
call mct_aVect_zero(x2a_ax_avg)
endif
if (lnd_present) then
call mct_aVect_zero(l2x_lx_avg)
call mct_aVect_zero(x2l_lx_avg)
endif
if (rof_present .and. ocnrof_prognostic) then
call mct_aVect_zero(r2x_rx_avg)
endif
if (ocn_present) then
call mct_aVect_zero(o2x_ox_avg)
call mct_aVect_zero(x2o_ox_avg)
endif
if (ice_present) then
call mct_aVect_zero(i2x_ix_avg)
call mct_aVect_zero(x2i_ix_avg)
endif
if (glc_present) then
call mct_aVect_zero(g2x_gx_avg)
call mct_aVect_zero(x2g_gx_avg)
endif
if (sno_present) then
call mct_aVect_zero(s2x_sx_avg)
call mct_aVect_zero(x2s_sx_avg)
endif
cnt = 0
tbnds(1) = curr_time
endif
endif
end subroutine seq_hist_writeavg
!===============================================================================
subroutine seq_hist_writeaux(EClock_d,aname,dname,cdata_av,av,nx,ny,nt,write_now,flds) 9,26
implicit none
type(ESMF_Clock), intent(in) :: EClock_d ! driver clock
character(*) , intent(in) :: aname ! avect name for hist file
character(*) , intent(in) :: dname ! domain name for hist file
type(seq_cdata) , intent(in) :: cdata_av ! cdata of avect
type(mct_aVect) , intent(in) :: av ! avect
integer(IN) , intent(in) :: nx ! 2d global size nx
integer(IN) , intent(in) :: ny ! 2d global size ny
integer(IN) , intent(in) :: nt ! number of time samples per file
logical,optional, intent(in) :: write_now ! write a sample now, if not used, write every call
character(*),intent(in),optional :: flds ! list of fields to write
!--- local ---
character(CL) :: case_name ! case name
type(mct_gGrid),pointer :: dom
integer(IN) :: curr_ymd ! Current date YYYYMMDD
integer(IN) :: curr_tod ! Current time-of-day (s)
integer(IN) :: start_ymd ! Starting date YYYYMMDD
integer(IN) :: start_tod ! Starting time-of-day (s)
real(r8) :: curr_time ! Time interval since reference time
real(r8) :: prev_time ! Time interval since reference time
integer(IN) :: yy,mm,dd ! year, month, day
integer(IN) :: n,fk,fk1 ! index
character(CL) :: time_units ! units of time variable
character(CL) :: calendar ! calendar type
integer(IN) :: samples_per_file
integer(IN) :: lsize ! local size of an aVect
logical :: first_call
integer(IN) :: found = -10
logical :: useavg
logical :: lwrite_now
logical :: whead,wdata ! for writing restart/history cdf files
real(r8) :: tbnds(2)
integer(IN),parameter :: maxout = 20
integer(IN) ,save :: ntout = 0
character(CS) ,save :: tname(maxout) = 'x1y2z3'
integer(IN) ,save :: ncnt(maxout) = -10
character(CL) ,save :: hist_file(maxout) ! local path to history filename
type(mct_aVect) ,save :: avavg(maxout) ! av accumulator if needed
integer(IN) ,save :: avcnt(maxout) = 0 ! accumulator counter
logical ,save :: fwrite(maxout) = .true. ! first write
real(r8) ,save :: tbnds1(maxout) ! first time_bnds
real(r8) ,save :: tbnds2(maxout) ! second time_bnds
type(mct_aVect) :: avflds ! non-avg av for a subset of fields
real(r8),parameter :: c0 = 0.0_r8 ! zero
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
!----------------------------------------------------------------------------
! 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, cpl_cdf64=cdf64 )
lwrite_now = .true.
useavg = .false.
if (present(write_now)) then
useavg = .true.
lwrite_now = write_now
endif
call seq_timemgr_EClockGetData
( EClock_d, curr_ymd=curr_ymd, curr_tod=curr_tod, &
start_ymd=start_ymd, start_tod=start_tod, curr_time=curr_time, prev_time=prev_time, &
calendar=calendar)
first_call = .true.
do n = 1,ntout
if (trim(tname(n)) == trim(aname)) then
first_call = .false.
found = n
endif
enddo
if (first_call) then
ntout = ntout + 1
if (ntout > maxout) then
write(logunit,*) 'write_history_spewAV maxout exceeded',ntout,maxout
call shr_sys_abort
()
endif
tname(ntout) = trim(aname)
ncnt(ntout) = -10
if (iamin_CPLID .and. useavg) then
lsize = mct_aVect_lsize(av)
call mct_aVect_init(avavg(ntout),av,lsize)
call mct_aVect_zero(avavg(ntout))
avcnt(ntout) = 0
endif
tbnds1(ntout) = prev_time
found = ntout
endif
! if (.not. iamin_CPLID) return
if (iamin_CPLID) then !>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
samples_per_file = nt
if (useavg) then
if (lwrite_now) then
avcnt(found) = avcnt(found) + 1
avavg(found)%rAttr = (avavg(found)%rAttr + av%rAttr) / (avcnt(found) * 1.0_r8)
else
avcnt(found) = avcnt(found) + 1
avavg(found)%rAttr = avavg(found)%rAttr + av%rAttr
endif
endif
if (lwrite_now) then
ncnt(found) = ncnt(found) + 1
if (ncnt(found) < 1 .or. ncnt(found) > samples_per_file) ncnt(found) = 1
time_units = 'days since ' &
// seq_io_date2yyyymmdd
(start_ymd) // ' ' // seq_io_sec2hms
(start_tod)
tbnds2(found) = curr_time
if (ncnt(found) == 1) then
fk1 = 1
call seq_infodata_GetData
( infodata, case_name=case_name)
call shr_cal_date2ymd
(curr_ymd,yy,mm,dd)
write(hist_file(found),"(a,i4.4,a,i2.2,a,i2.2,a)") &
trim(case_name)//'.cpl.h'//trim(aname)//'.', yy,'-',mm,'-',dd,'.nc'
else
fk1 = 2
endif
call seq_cdata_setptrs
(cdata_av, dom=dom)
if (drv_threading) call seq_comm_setnthreads
(nthreads_CPLID)
if (fk1 == 1) then
call seq_io_wopen
(hist_file(found),cdata_av,clobber=.true.,cdf64=cdf64)
else
call seq_io_wopen
(hist_file(found),cdata_av,clobber=.false.,cdf64=cdf64)
endif
! loop twice, first time write header, second time write data for perf
tbnds(1) = tbnds1(found)
tbnds(2) = tbnds2(found)
do fk = fk1,2
if (fk == 1) then
whead = .true.
wdata = .false.
elseif (fk == 2) then
whead = .false.
wdata = .true.
else
call shr_sys_abort
('seq_hist_writeaux fk illegal')
end if
if (present(flds)) then
if (fk == fk1) then
lsize = mct_aVect_lsize(av)
call mct_aVect_init(avflds, rList=flds, lsize=lsize)
call mct_aVect_zero(avflds)
end if
end if
call seq_io_write
(hist_file(found),&
time_units=time_units,time_cal=calendar,time_val=curr_time,&
nt=ncnt(found),whead=whead,wdata=wdata,tbnds=tbnds)
if (fwrite(found)) then
call seq_io_write
(hist_file(found),cdata_av,dom%data,trim(dname), &
nx=nx,ny=ny,whead=whead,wdata=wdata,fillval=c0,pre=trim(dname))
endif
if (useavg) then
if (present(flds)) then
call mct_aVect_copy(aVin=avavg(found), aVout=avflds)
call seq_io_write
(hist_file(found), cdata_av, avflds, trim(aname), &
nx=nx, ny=ny, nt=ncnt(found), whead=whead, wdata=wdata, &
pre=trim(aname),tavg=.true.,use_float=.true.)
else
call seq_io_write
(hist_file(found), cdata_av, avavg(found), trim(aname), &
nx=nx, ny=ny, nt=ncnt(found), whead=whead, wdata=wdata, &
pre=trim(aname),tavg=.true., use_float=.true.)
end if
else if (present(flds)) then
call mct_aVect_copy(aVin=av, aVout=avflds)
call seq_io_write
(hist_file(found), cdata_av, avflds, trim(aname), &
nx=nx,ny=ny,nt=ncnt(found),whead=whead,wdata=wdata,pre=trim(aname),&
use_float=.true.)
else
call seq_io_write
(hist_file(found), cdata_av, av, trim(aname), &
nx=nx,ny=ny,nt=ncnt(found),whead=whead,wdata=wdata,pre=trim(aname),&
use_float=.true.)
endif
if (present(flds)) then
if (fk == 2) then
call mct_aVect_clean(avflds)
end if
end if
if (fk == 1) call seq_io_enddef
(hist_file(found))
if (fk == 2) then
fwrite(found) = .false.
if (useavg) then
call mct_aVect_zero(avavg(found))
avcnt(found) = 0
endif
tbnds1(found) = curr_time
endif
enddo
call seq_io_close
(hist_file(found),cdata_av)
if (drv_threading) call seq_comm_setnthreads
(nthreads_GLOID)
endif ! lwrite_now
endif ! iamin_CPLID <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
end subroutine seq_hist_writeaux
!===============================================================================
end module seq_hist_mod