#ifdef AIX
@PROCESS ALIAS_SIZE(805306368)
#endif
module datm_comp_mod 1,16
! !USES:
use shr_const_mod
use shr_sys_mod
use shr_kind_mod
, only: IN=>SHR_KIND_IN, R8=>SHR_KIND_R8, &
CS=>SHR_KIND_CS, CL=>SHR_KIND_CL
use shr_file_mod
, only: shr_file_getunit, shr_file_getlogunit, shr_file_getloglevel, &
shr_file_setlogunit, shr_file_setloglevel, shr_file_setio, &
shr_file_freeunit
use shr_cal_mod
, only: shr_cal_date2eday
use shr_mpi_mod
, only: shr_mpi_bcast
use mct_mod
use esmf_mod
use perf_mod
use shr_strdata_mod
use shr_dmodel_mod
use shr_pcdf_mod
use datm_shr_mod
use seq_cdata_mod
use seq_infodata_mod
use seq_timemgr_mod
use seq_flds_indices
, only: nflds_a2x, &
nflds_x2a
use seq_flds_mod
, only: seq_flds_a2x_fields, &
seq_flds_x2a_fields
!
! !PUBLIC TYPES:
implicit none
private ! except
!--------------------------------------------------------------------------
! Public interfaces
!--------------------------------------------------------------------------
public :: datm_comp_init
public :: datm_comp_run
public :: datm_comp_final
!--------------------------------------------------------------------------
! Private data
!--------------------------------------------------------------------------
!--- other ---
character(CS) :: myModelName = 'atm' ! user defined model name
integer(IN) :: mpicom
integer(IN) :: COMPID ! mct comp id
integer(IN) :: my_task ! my task in mpi communicator mpicom
integer(IN) :: npes ! total number of tasks
integer(IN),parameter :: master_task=0 ! task number of master task
integer(IN) :: logunit ! logging unit number
character(CL) :: atm_mode ! mode
integer(IN) :: dbug = 0 ! debug level (higher is more)
logical :: firstcall = .true. ! first call logical
logical :: scmMode = .false. ! single column mode
real(R8) :: scmLat = shr_const_SPVAL ! single column lat
real(R8) :: scmLon = shr_const_SPVAL ! single column lon
integer :: phase ! phase of method
logical :: read_restart ! start from restart
real(R8) :: orbEccen ! orb eccentricity (unit-less)
real(R8) :: orbMvelpp ! orb moving vernal eq (radians)
real(R8) :: orbLambm0 ! orb mean long of perhelion (radians)
real(R8) :: orbObliqr ! orb obliquity (radians)
real(R8) :: tbotmax ! units detector
real(R8) :: tdewmax ! units detector
real(R8) :: anidrmax ! existance detector
integer(IN) :: iradsw ! radiation logical
character(CL) :: factorFn ! file containing correction factors
character(len=*),parameter :: rpfile = 'rpointer.atm'
character(len=*),parameter :: nullstr = 'undefined'
real(R8),parameter :: aerodep_spval = 1.e29_r8 ! special aerosol deposition
real(R8),parameter :: tKFrz = SHR_CONST_TKFRZ
real(R8),parameter :: degtorad = SHR_CONST_PI/180.0_R8
real(R8),parameter :: pstd = SHR_CONST_PSTD ! standard pressure ~ Pa
real(R8),parameter :: stebol = SHR_CONST_STEBOL ! Stefan-Boltzmann constant ~ W/m^2/K^4
real(R8),parameter :: rdair = SHR_CONST_RDAIR ! dry air gas constant ~ J/K/kg
real(R8),parameter :: avg_c0 = 61.846_R8
real(R8),parameter :: avg_c1 = 1.107_R8
real(R8),parameter :: amp_c0 = -21.841_R8
real(R8),parameter :: amp_c1 = -0.447_R8
real(R8),parameter :: phs_c0 = 0.298_R8
real(R8),parameter :: dLWarc = -5.000_R8
real(R8) ,save :: dTarc(12)
data dTarc / 0.49_R8, 0.06_R8,-0.73_R8, -0.89_R8,-0.77_R8,-1.02_R8, &
& -1.99_R8,-0.91_R8, 1.72_R8, 2.30_R8, 1.81_R8, 1.06_R8/
integer(IN) :: kz,ku,kv,ktbot,kptem,kshum,kdens,kpbot,kpslv,klwdn
integer(IN) :: krc,krl,ksc,ksl,kswndr,kswndf,kswvdr,kswvdf,kswnet,kco2p,kco2d
integer(IN) :: kbid,kbod,kbiw,koid,kood,koiw,kdw1,kdw2,kdw3,kdw4,kdd1,kdd2,kdd3,kdd4
integer(IN) :: kanidr,kanidf,kavsdr,kavsdf
integer(IN) :: stbot,swind,sz,spbot,sshum,stdew,srh,slwdn,sswdn,sswdndf,sswdndr
integer(IN) :: sprecc,sprecl,sprecn,sco2p,sco2d,sswup,sprec
type(shr_strdata_type) :: SDATM
type(mct_rearr) :: rearr
type(mct_avect) :: avstrm ! av of data from stream
integer(IN), pointer :: imask(:)
real(R8), pointer :: yc(:)
real(R8), pointer :: windFactor(:)
real(R8), pointer :: winddFactor(:)
real(R8), pointer :: qsatFactor(:)
integer(IN),parameter :: ktrans = 56
character(16),parameter :: avofld(1:ktrans) = &
(/"Sa_z ","Sa_u ","Sa_v ","Sa_tbot ", &
"Sa_ptem ","Sa_shum ","Sa_dens ","Sa_pbot ", &
"Sa_pslv ","Faxa_lwdn ","Faxa_rainc ","Faxa_rainl ", &
"Faxa_snowc ","Faxa_snowl ","Faxa_swndr ","Faxa_swvdr ", &
"Faxa_swndf ","Faxa_swvdf ","Faxa_swnet ","Sa_co2prog ", &
"Sa_co2diag ","Faxa_bcphidry ","Faxa_bcphodry ","Faxa_bcphiwet ", &
"Faxa_ocphidry ","Faxa_ocphodry ","Faxa_ocphiwet ","Faxa_dstwet1 ", &
"Faxa_dstwet2 ","Faxa_dstwet3 ","Faxa_dstwet4 ","Faxa_dstdry1 ", &
"Faxa_dstdry2 ","Faxa_dstdry3 ","Faxa_dstdry4 ", &
"Sx_tref ","Sx_qref ","Sx_avsdr ","Sx_anidr ", &
"Sx_avsdf ","Sx_anidf ","Sx_t ","So_t ", &
"Sx_snowh ","Sx_lfrac ","Sx_ifrac ","Sx_ofrac ", &
"Faxx_taux ","Faxx_tauy ","Faxx_lat ","Faxx_sen ", &
"Faxx_lwup ","Faxx_evap ","Faxx_fco2_lnd ","Faxx_fco2_ocn ", &
"Faxx_fdms " /)
character(16),parameter :: avifld(1:ktrans) = &
(/"z ","u ","v ","tbot ", &
"ptem ","shum ","dens ","pbot ", &
"pslv ","lwdn ","rainc ","rainl ", &
"snowc ","snowl ","swndr ","swvdr ", &
"swndf ","swvdf ","swnet ","co2prog ", &
"co2diag ","bcphidry ","bcphodry ","bcphiwet ", &
"ocphidry ","ocphodry ","ocphiwet ","dstwet1 ", &
"dstwet2 ","dstwet3 ","dstwet4 ","dstdry1 ", &
"dstdry2 ","dstdry3 ","dstdry4 ", &
"tref ","qref ","avsdr ","anidr ", &
"avsdf ","anidf ","ts ","to ", &
"snowh ","lfrac ","ifrac ","ofrac ", &
"taux ","tauy ","lat ","sen ", &
"lwup ","evap ","co2lnd ","co2ocn ", &
"dms " /)
integer(IN),parameter :: ktranss = 18
character(16),parameter :: stofld(1:ktranss) = &
(/"strm_tbot ","strm_wind ","strm_z ","strm_pbot ", &
"strm_shum ","strm_tdew ","strm_rh ","strm_lwdn ", &
"strm_swdn ","strm_swdndf ","strm_swdndr ","strm_precc ", &
"strm_precl ","strm_precn ","strm_co2prog ","strm_co2diag ", &
"strm_swup ","strm_prec " /)
character(16),parameter :: stifld(1:ktranss) = &
(/"tbot ","wind ","z ","pbot ", &
"shum ","tdew ","rh ","lwdn ", &
"swdn ","swdndf ","swdndr ","precc ", &
"precl ","precn ","co2prog ","co2diag ", &
"swup ","prec " /)
save
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CONTAINS
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: datm_comp_init
!
! !DESCRIPTION:
! initialize data atm model
!
! !REVISION HISTORY:
!
! !INTERFACE: ------------------------------------------------------------------
subroutine datm_comp_init( EClock, cdata, x2a, a2x, NLFilename ) 2,49
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(ESMF_Clock) , intent(in) :: EClock
type(seq_cdata) , intent(inout) :: cdata
type(mct_aVect) , intent(inout) :: x2a, a2x
character(len=*), optional , intent(in) :: NLFilename ! Namelist filename
!EOP
!--- local variables ---
integer(IN) :: n,k ! generic counters
integer(IN) :: ierr ! error code
integer(IN) :: gsize ! global size
integer(IN) :: lsize ! local size
integer(IN) :: shrlogunit, shrloglev ! original log unit and level
integer(IN) :: nunit ! unit number
integer(IN) :: kmask ! field reference
integer(IN) :: klat ! field reference
integer(IN) :: kfld ! fld index
integer(IN) :: cnt ! counter
logical :: atm_present ! flag
logical :: atm_prognostic ! flag
type(seq_infodata_type), pointer :: infodata
type(mct_gsMap) , pointer :: gsMap
type(mct_gGrid) , pointer :: ggrid
character(CL) :: filePath ! generic file path
character(CL) :: fileName ! generic file name
character(CS) :: timeName ! domain file: time variable name
character(CS) :: lonName ! domain file: lon variable name
character(CS) :: latName ! domain file: lat variable name
character(CS) :: maskName ! domain file: mask variable name
character(CS) :: areaName ! domain file: area variable name
integer(IN) :: yearFirst ! first year to use in data stream
integer(IN) :: yearLast ! last year to use in data stream
integer(IN) :: yearAlign ! data year that aligns with yearFirst
character(CL) :: atm_in ! dshr atm namelist
character(CL) :: decomp ! decomp strategy
character(CL) :: rest_file ! restart filename
character(CL) :: rest_file_strm ! restart filename for streams
character(CL) :: restfilm ! model restart file namelist
character(CL) :: restfils ! stream restart file namelist
logical :: exists ! filename existance
integer(IN) :: nu ! unit number
integer(IN) :: idt ! integer timestep
integer(IN) :: CurrentYMD ! model date
integer(IN) :: CurrentTOD ! model sec into model date
integer(IN) :: stepno ! step number
real(R8) :: nextsw_cday ! calendar of next atm sw
character(CL) :: flds_strm
logical :: presaero ! true => send valid prescribe aero fields to coupler
!----- define namelist -----
namelist / datm_nml / &
atm_in, decomp, iradsw, factorFn, restfilm, restfils, presaero
!--- formats ---
character(*), parameter :: F00 = "('(datm_comp_init) ',8a)"
character(*), parameter :: F0L = "('(datm_comp_init) ',a, l)"
character(*), parameter :: F01 = "('(datm_comp_init) ',a,5i8)"
character(*), parameter :: F02 = "('(datm_comp_init) ',a,4es13.6)"
character(*), parameter :: F03 = "('(datm_comp_init) ',a,i8,a)"
character(*), parameter :: F04 = "('(datm_comp_init) ',2a,2i8,'s')"
character(*), parameter :: F05 = "('(datm_comp_init) ',a,2f10.4)"
character(*), parameter :: F90 = "('(datm_comp_init) ',73('='))"
character(*), parameter :: F91 = "('(datm_comp_init) ',73('-'))"
character(*), parameter :: subName = "(datm_comp_init) "
!-------------------------------------------------------------------------------
call t_startf('DATM_INIT')
! Set cdata pointers
call seq_cdata_setptrs
(cdata, ID=COMPID, mpicom=mpicom, &
gsMap=gsmap, dom=ggrid, infodata=infodata)
call seq_infodata_getData
(infodata,atm_phase=phase)
if (phase == 1) then
! Determine communicator groups and sizes
call mpi_comm_rank(mpicom, my_task, ierr)
call mpi_comm_size(mpicom, npes, ierr)
!--- open log file ---
if (my_task == master_task) then
logUnit = shr_file_getUnit
()
call shr_file_setIO
('atm_modelio.nml',logUnit)
else
logUnit = 6
endif
endif
!----------------------------------------------------------------------------
! Reset shr logging to my log file
!----------------------------------------------------------------------------
call shr_file_getLogUnit
(shrlogunit)
call shr_file_getLogLevel
(shrloglev)
call shr_file_setLogUnit
(logUnit)
if (phase == 1) then
!----------------------------------------------------------------------------
! Set a Few Defaults
!----------------------------------------------------------------------------
call seq_infodata_getData
(infodata,single_column=scmMode, &
& scmlat=scmlat, scmlon=scmLon)
call seq_infodata_GetData
(infodata,orb_eccen=orbEccen,orb_mvelpp=orbMvelpp, &
orb_lambm0=orbLambm0,orb_obliqr=orbObliqr )
atm_present = .false.
atm_prognostic = .false.
call seq_infodata_GetData
(infodata,read_restart=read_restart)
!----------------------------------------------------------------------------
! Read datm_in
!----------------------------------------------------------------------------
call t_startf('datm_readnml')
filename = "datm_in"
atm_in = "unset"
decomp = "1d"
iradsw = 0
factorFn = 'null'
restfilm = trim(nullstr)
restfils = trim(nullstr)
presaero = .false.
if (my_task == master_task) then
nunit = shr_file_getUnit
() ! get unused unit number
open (nunit,file=trim(filename),status="old",action="read")
read (nunit,nml=datm_nml,iostat=ierr)
close(nunit)
call shr_file_freeUnit
(nunit)
if (ierr > 0) then
write(logunit,F01) 'ERROR: reading input namelist, '//trim(filename)//' iostat=',ierr
call shr_sys_abort
(subName//': namelist read error '//trim(filename))
end if
write(logunit,F00)' atm_in = ',trim(atm_in)
write(logunit,F00)' decomp = ',trim(decomp)
write(logunit,F01)' iradsw = ',iradsw
write(logunit,F00)' factorFn = ',trim(factorFn)
write(logunit,F00)' restfilm = ',trim(restfilm)
write(logunit,F00)' restfils = ',trim(restfils)
write(logunit,F0L)' presaero = ',presaero
endif
call shr_mpi_bcast(atm_in,mpicom,'atm_in')
call shr_mpi_bcast(decomp,mpicom,'decomp')
call shr_mpi_bcast(iradsw,mpicom,'iradsw')
call shr_mpi_bcast(factorFn,mpicom,'factorFn')
call shr_mpi_bcast(restfilm,mpicom,'restfilm')
call shr_mpi_bcast(restfils,mpicom,'restfils')
call shr_mpi_bcast(presaero,mpicom,'presaero')
rest_file = trim(restfilm)
rest_file_strm = trim(restfils)
!----------------------------------------------------------------------------
! Read dshr namelist
!----------------------------------------------------------------------------
call shr_strdata_readnml
(SDATM,trim(atm_in),mpicom=mpicom)
!----------------------------------------------------------------------------
! Validate mode
!----------------------------------------------------------------------------
atm_mode = trim(SDATM%dataMode)
! check that we know how to handle the mode
if (trim(atm_mode) == 'NULL' .or. &
trim(atm_mode) == 'TN460' .or. &
trim(atm_mode) == 'CORE2' .or. &
trim(atm_mode) == 'CLMNCEP' .or. &
trim(atm_mode) == 'CPLHIST' .or. &
trim(atm_mode) == 'COPYALL') then
if (my_task == master_task) &
write(logunit,F00) ' atm mode = ',trim(atm_mode)
else
write(logunit,F00) ' ERROR illegal atm mode = ',trim(atm_mode)
call shr_sys_abort
()
endif
call t_stopf('datm_readnml')
!----------------------------------------------------------------------------
! Initialize datasets
!----------------------------------------------------------------------------
call t_startf('datm_strdata_init')
if (trim(atm_mode) /= 'NULL') then
atm_present = .true.
if (scmmode) then
if (my_task == master_task) &
write(logunit,F05) ' scm lon lat = ',scmlon,scmlat
call shr_strdata_init
(SDATM,mpicom,compid,name='atm', &
scmmode=scmmode,scmlon=scmlon,scmlat=scmlat)
else
call shr_strdata_init
(SDATM,mpicom,compid,name='atm')
endif
!--- overwrite mask and frac ---
k = mct_aVect_indexRA(SDATM%grid%data,'mask')
SDATM%grid%data%rAttr(k,:) = 1.0_R8
k = mct_aVect_indexRA(SDATM%grid%data,'frac')
SDATM%grid%data%rAttr(k,:) = 1.0_R8
!--- set data needed for cosz t-interp method ---
call seq_timemgr_EClockGetData
( EClock, dtime=idt )
call shr_strdata_setOrbs
(SDATM,orbEccen,orbMvelpp,orbLambm0,orbObliqr,idt)
endif
if (my_task == master_task) then
call shr_strdata_print
(SDATM,'ATM data')
endif
call t_stopf('datm_strdata_init')
!----------------------------------------------------------------------------
! Set flag to specify data components
!----------------------------------------------------------------------------
call seq_infodata_PutData
(infodata, &
atm_present=atm_present, atm_prognostic=atm_prognostic, &
atm_nx=SDATM%nxg, atm_ny=SDATM%nyg )
call seq_infodata_PutData
( infodata, atm_aero=presaero)
!----------------------------------------------------------------------------
! Initialize MCT global seg map, 1d decomp
!----------------------------------------------------------------------------
call t_startf('datm_initgsmaps')
if (my_task == master_task) write(logunit,F00) ' initialize gsmaps'
call shr_sys_flush
(logunit)
call shr_dmodel_gsmapcreate
(gsmap,SDATM%nxg*SDATM%nyg,compid,mpicom,decomp)
lsize = mct_gsmap_lsize(gsmap,mpicom)
if (atm_present) then
call mct_rearr_init(SDATM%gsmap,gsmap,mpicom,rearr)
endif
call t_stopf('datm_initgsmaps')
!----------------------------------------------------------------------------
! Initialize MCT domain
!----------------------------------------------------------------------------
call t_startf('datm_initmctdom')
if (my_task == master_task) write(logunit,F00) 'copy domains'
call shr_sys_flush
(logunit)
if (atm_present) call shr_dmodel_rearrGGrid
(SDATM%grid, ggrid, gsmap, rearr, mpicom)
call t_stopf('datm_initmctdom')
!----------------------------------------------------------------------------
! Initialize MCT attribute vectors
!----------------------------------------------------------------------------
call t_startf('datm_initmctavs')
if (my_task == master_task) write(logunit,F00) 'allocate AVs'
call shr_sys_flush
(logunit)
call mct_aVect_init(a2x, rList=seq_flds_a2x_fields, lsize=lsize)
call mct_aVect_zero(a2x)
kz = mct_aVect_indexRA(a2x,'Sa_z')
ku = mct_aVect_indexRA(a2x,'Sa_u')
kv = mct_aVect_indexRA(a2x,'Sa_v')
ktbot = mct_aVect_indexRA(a2x,'Sa_tbot')
kptem = mct_aVect_indexRA(a2x,'Sa_ptem')
kshum = mct_aVect_indexRA(a2x,'Sa_shum')
kdens = mct_aVect_indexRA(a2x,'Sa_dens')
kpbot = mct_aVect_indexRA(a2x,'Sa_pbot')
kpslv = mct_aVect_indexRA(a2x,'Sa_pslv')
klwdn = mct_aVect_indexRA(a2x,'Faxa_lwdn')
krc = mct_aVect_indexRA(a2x,'Faxa_rainc')
krl = mct_aVect_indexRA(a2x,'Faxa_rainl')
ksc = mct_aVect_indexRA(a2x,'Faxa_snowc')
ksl = mct_aVect_indexRA(a2x,'Faxa_snowl')
kswndr= mct_aVect_indexRA(a2x,'Faxa_swndr')
kswndf= mct_aVect_indexRA(a2x,'Faxa_swndf')
kswvdr= mct_aVect_indexRA(a2x,'Faxa_swvdr')
kswvdf= mct_aVect_indexRA(a2x,'Faxa_swvdf')
kswnet= mct_aVect_indexRA(a2x,'Faxa_swnet')
kco2p = mct_aVect_indexRA(a2x,'Sa_co2prog',perrWith='quiet')
kco2d = mct_aVect_indexRA(a2x,'Sa_co2diag',perrWith='quiet')
kbid = mct_aVect_indexRA(a2x,'Faxa_bcphidry')
kbod = mct_aVect_indexRA(a2x,'Faxa_bcphodry')
kbiw = mct_aVect_indexRA(a2x,'Faxa_bcphiwet')
koid = mct_aVect_indexRA(a2x,'Faxa_ocphidry')
kood = mct_aVect_indexRA(a2x,'Faxa_ocphodry')
koiw = mct_aVect_indexRA(a2x,'Faxa_ocphiwet')
kdd1 = mct_aVect_indexRA(a2x,'Faxa_dstdry1')
kdd2 = mct_aVect_indexRA(a2x,'Faxa_dstdry2')
kdd3 = mct_aVect_indexRA(a2x,'Faxa_dstdry3')
kdd4 = mct_aVect_indexRA(a2x,'Faxa_dstdry4')
kdw1 = mct_aVect_indexRA(a2x,'Faxa_dstwet1')
kdw2 = mct_aVect_indexRA(a2x,'Faxa_dstwet2')
kdw3 = mct_aVect_indexRA(a2x,'Faxa_dstwet3')
kdw4 = mct_aVect_indexRA(a2x,'Faxa_dstwet4')
call mct_aVect_init(x2a, rList=seq_flds_x2a_fields, lsize=lsize)
call mct_aVect_zero(x2a)
kanidr = mct_aVect_indexRA(x2a,'Sx_anidr')
kanidf = mct_aVect_indexRA(x2a,'Sx_anidf')
kavsdr = mct_aVect_indexRA(x2a,'Sx_avsdr')
kavsdf = mct_aVect_indexRA(x2a,'Sx_avsdf')
!--- figure out what's on the streams ---
cnt = 0
flds_strm = ''
do n = 1,SDATM%nstreams
do k = 1,ktranss
kfld = mct_aVect_indexRA(SDATM%avs(n),trim(stifld(k)),perrWith='quiet')
if (kfld > 0) then
cnt = cnt + 1
if (cnt == 1) then
flds_strm = trim(stofld(k))
else
flds_strm = trim(flds_strm)//':'//trim(stofld(k))
endif
endif
enddo
enddo
if (my_task == master_task) write(logunit,F00) ' flds_strm = ',trim(flds_strm)
call shr_sys_flush
(logunit)
call mct_aVect_init(avstrm, rList=flds_strm, lsize=lsize)
call mct_aVect_zero(avstrm)
stbot = mct_aVect_indexRA(avstrm,'strm_tbot',perrWith='quiet')
swind = mct_aVect_indexRA(avstrm,'strm_wind',perrWith='quiet')
sz = mct_aVect_indexRA(avstrm,'strm_z',perrWith='quiet')
spbot = mct_aVect_indexRA(avstrm,'strm_pbot',perrWith='quiet')
sshum = mct_aVect_indexRA(avstrm,'strm_shum',perrWith='quiet')
stdew = mct_aVect_indexRA(avstrm,'strm_tdew',perrWith='quiet')
srh = mct_aVect_indexRA(avstrm,'strm_rh',perrWith='quiet')
slwdn = mct_aVect_indexRA(avstrm,'strm_lwdn',perrWith='quiet')
sswdn = mct_aVect_indexRA(avstrm,'strm_swdn',perrWith='quiet')
sswdndf= mct_aVect_indexRA(avstrm,'strm_swdndf',perrWith='quiet')
sswdndr= mct_aVect_indexRA(avstrm,'strm_swdndr',perrWith='quiet')
sprecc = mct_aVect_indexRA(avstrm,'strm_precc',perrWith='quiet')
sprecl = mct_aVect_indexRA(avstrm,'strm_precl',perrWith='quiet')
sprecn = mct_aVect_indexRA(avstrm,'strm_precn',perrWith='quiet')
sco2p = mct_aVect_indexRA(avstrm,'strm_co2p',perrWith='quiet')
sco2d = mct_aVect_indexRA(avstrm,'strm_co2d',perrWith='quiet')
sswup = mct_aVect_indexRA(avstrm,'strm_swup',perrWith='quiet')
sprec = mct_aVect_indexRA(avstrm,'strm_prec',perrWith='quiet')
allocate(imask(lsize))
allocate(yc(lsize))
allocate(windFactor(lsize))
allocate(winddFactor(lsize))
allocate(qsatFactor(lsize))
kmask = mct_aVect_indexRA(ggrid%data,'mask')
imask(:) = nint(ggrid%data%rAttr(kmask,:))
klat = mct_aVect_indexRA(ggrid%data,'lat')
yc(:) = ggrid%data%rAttr(klat,:)
call t_stopf('datm_initmctavs')
!----------------------------------------------------------------------------
! Read restart
!----------------------------------------------------------------------------
if (read_restart) then
if (trim(rest_file) == trim(nullstr) .and. &
trim(rest_file_strm) == trim(nullstr)) then
if (my_task == master_task) then
write(logunit,F00) ' restart filenames from rpointer'
call shr_sys_flush
(logunit)
inquire(file=trim(rpfile),exist=exists)
if (.not.exists) then
write(logunit,F00) ' ERROR: rpointer file does not exist'
call shr_sys_abort
(trim(subname)//' ERROR: rpointer file missing')
endif
nu = shr_file_getUnit
()
open(nu,file=trim(rpfile),form='formatted')
read(nu,'(a)') rest_file
read(nu,'(a)') rest_file_strm
close(nu)
call shr_file_freeUnit
(nu)
inquire(file=trim(rest_file_strm),exist=exists)
endif
call shr_mpi_bcast(rest_file,mpicom,'rest_file')
call shr_mpi_bcast(rest_file_strm,mpicom,'rest_file_strm')
else
! use namelist already read
if (my_task == master_task) then
write(logunit,F00) ' restart filenames from namelist '
call shr_sys_flush
(logunit)
inquire(file=trim(rest_file_strm),exist=exists)
endif
endif
call shr_mpi_bcast(exists,mpicom,'exists')
! if (my_task == master_task) write(logunit,F00) ' reading ',trim(rest_file)
! call shr_pcdf_readwrite('read',trim(rest_file),mpicom,gsmap,rf1=somtp,rf1n='somtp')
if (exists) then
if (my_task == master_task) write(logunit,F00) ' reading ',trim(rest_file_strm)
call shr_strdata_restRead
(trim(rest_file_strm),SDATM,mpicom)
else
if (my_task == master_task) write(logunit,F00) ' file not found, skipping ',trim(rest_file_strm)
endif
call shr_sys_flush
(logunit)
endif
if (read_restart) then
call seq_timemgr_EClockGetData
( EClock, curr_ymd=CurrentYMD, curr_tod=CurrentTOD)
call seq_timemgr_EClockGetData
( EClock, stepno=stepno, dtime=idt )
nextsw_cday = datm_shr_getNextRadCDay
( CurrentYMD, CurrentTOD, stepno, idt, iradsw )
else
call seq_timemgr_EClockGetData
( EClock, curr_cday=nextsw_cday, stepno=stepno )
endif
call seq_infodata_PutData
(infodata, nextsw_cday=nextsw_cday )
else
call seq_timemgr_EClockGetData
( EClock, curr_ymd=CurrentYMD, curr_tod=CurrentTOD)
call seq_timemgr_EClockGetData
( EClock, stepno=stepno, dtime=idt)
nextsw_cday = datm_shr_getNextRadCDay
( CurrentYMD, CurrentTOD, stepno, idt, iradsw )
call seq_infodata_PutData
(infodata, nextsw_cday=nextsw_cday )
endif
!----------------------------------------------------------------------------
! Set initial atm state, needed for CCSM atm initialization
!----------------------------------------------------------------------------
call t_adj_detailf(+2)
call datm_comp_run
( EClock, cdata, x2a, a2x)
call t_adj_detailf(-2)
!----------------------------------------------------------------------------
! Reset shr logging to original values
!----------------------------------------------------------------------------
if (my_task == master_task) write(logunit,F00) 'datm_comp_init done'
call shr_sys_flush
(logunit)
call shr_file_setLogUnit
(shrlogunit)
call shr_file_setLogLevel
(shrloglev)
call shr_sys_flush
(logunit)
call t_stopf('DATM_INIT')
end subroutine datm_comp_init
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: datm_comp_run
!
! !DESCRIPTION:
! run method for dead atm model
!
! !REVISION HISTORY:
!
! !INTERFACE: ------------------------------------------------------------------
subroutine datm_comp_run( EClock, cdata, x2a, a2x) 2,37
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(ESMF_Clock) ,intent(in) :: EClock
type(seq_cdata) ,intent(inout) :: cdata
type(mct_aVect) ,intent(inout) :: x2a ! driver -> dead
type(mct_aVect) ,intent(inout) :: a2x ! dead -> driver
!EOP
!--- local ---
type(mct_gsMap) , pointer :: gsMap
type(mct_gGrid) , pointer :: ggrid
integer(IN) :: CurrentYMD ! model date
integer(IN) :: CurrentTOD ! model sec into model date
integer(IN) :: yy,mm,dd ! year month day
integer(IN) :: n ! indices
integer(IN) :: lsize ! size of attr vect
integer(IN) :: shrlogunit, shrloglev ! original log unit and level
logical :: mssrmlf ! remove old data
integer(IN) :: idt ! integer timestep
real(R8) :: dt ! timestep
logical :: write_restart ! restart now
character(CL) :: case_name ! case name
character(CL) :: rest_file ! restart_file
character(CL) :: rest_file_strm ! restart_file
integer(IN) :: nu ! unit number
integer(IN) :: stepno ! step number
real(R8) :: nextsw_cday ! calendar of next atm sw
integer(IN) :: eday ! elapsed day
real(R8) :: rday ! elapsed day
real(R8) :: cosFactor ! cosine factor
real(R8) :: factor ! generic/temporary correction factor
real(R8) :: avg_alb ! average albedo
real(R8) :: tMin ! minimum temperature
!--- temporaries
real(R8) :: uprime,vprime,swndr,swndf,swvdr,swvdf,ratio_rvrf
real(R8) :: tbot,pbot,rtmp,vp,ea,e,qsat,frac,qsatT
type(seq_infodata_type), pointer :: infodata
character(*), parameter :: F00 = "('(datm_comp_run) ',8a)"
character(*), parameter :: F04 = "('(datm_comp_run) ',2a,2i8,'s')"
character(*), parameter :: subName = "(datm_comp_run) "
!-------------------------------------------------------------------------------
call t_startf('DATM_RUN')
call t_startf('datm_run1')
!----------------------------------------------------------------------------
! Reset shr logging to my log file
!----------------------------------------------------------------------------
call shr_file_getLogUnit
(shrlogunit)
call shr_file_getLogLevel
(shrloglev)
call shr_file_setLogUnit
(logUnit)
call seq_cdata_setptrs
(cdata, gsMap=gsmap, dom=ggrid)
call seq_cdata_setptrs
(cdata, infodata=infodata)
call seq_timemgr_EClockGetData
( EClock, curr_ymd=CurrentYMD, curr_tod=CurrentTOD)
call seq_timemgr_EClockGetData
( EClock, curr_yr=yy, curr_mon=mm, curr_day=dd)
call seq_timemgr_EClockGetData
( EClock, stepno=stepno, dtime=idt)
dt = idt * 1.0_r8
write_restart = seq_timemgr_RestartAlarmIsOn
(EClock)
call t_stopf('datm_run1')
!--------------------
! ADVANCE ATM
!--------------------
call t_barrierf('datm_BARRIER',mpicom)
call t_startf('datm')
nextsw_cday = datm_shr_getNextRadCDay
( CurrentYMD, CurrentTOD, stepno, idt, iradsw )
call seq_infodata_PutData
(infodata, nextsw_cday=nextsw_cday )
!--- copy all fields from streams to a2x as default ---
if (trim(atm_mode) /= 'NULL') then
call t_startf('datm_strdata_advance')
call shr_strdata_advance
(SDATM,currentYMD,currentTOD,mpicom,'datm')
call t_stopf('datm_strdata_advance')
call t_barrierf('datm_scatter_BARRIER',mpicom)
call t_startf('datm_scatter')
if (trim(atm_mode) /= 'COPYALL') then
lsize = mct_avect_lsize(a2x)
do n = 1,lsize
a2x%rAttr(kbid,n) = aerodep_spval
a2x%rAttr(kbod,n) = aerodep_spval
a2x%rAttr(kbiw,n) = aerodep_spval
a2x%rAttr(koid,n) = aerodep_spval
a2x%rAttr(kood,n) = aerodep_spval
a2x%rAttr(koiw,n) = aerodep_spval
a2x%rAttr(kdd1,n) = aerodep_spval
a2x%rAttr(kdd2,n) = aerodep_spval
a2x%rAttr(kdd3,n) = aerodep_spval
a2x%rAttr(kdd4,n) = aerodep_spval
a2x%rAttr(kdw1,n) = aerodep_spval
a2x%rAttr(kdw2,n) = aerodep_spval
a2x%rAttr(kdw3,n) = aerodep_spval
a2x%rAttr(kdw4,n) = aerodep_spval
enddo
endif
do n = 1,SDATM%nstreams
call shr_dmodel_translateAV
(SDATM%avs(n),a2x,avifld,avofld,rearr)
enddo
do n = 1,SDATM%nstreams
call shr_dmodel_translateAV
(SDATM%avs(n),avstrm,stifld,stofld,rearr)
enddo
call t_stopf('datm_scatter')
else
call mct_aVect_zero(a2x)
endif
call t_startf('datm_mode')
select case (trim(atm_mode))
case('COPYALL')
! do nothing extra
case('CPLHIST')
! do nothing extra
case('TN460')
if (firstcall) then
if (sprec < 1 .or. sswdn < 1 .or. sswup < 1) then
write(logunit,F00) ' ERROR: prec swdn and swup must be in streams for TN460'
call shr_sys_abort
(trim(subname)//' ERROR: prec swdn and swup must be in streams for TN460')
endif
call datm_shr_TN460getFactors
(factorFn,windFactor,qsatFactor, &
mpicom,compid,gsmap,ggrid,SDATM%nxg,SDATM%nyg)
endif
call shr_cal_date2eday
(currentYMD,eday)
rday = mod(eday,365) + real(currentTOD)/SHR_CONST_CDAY
cosfactor = cos((2.0_R8*SHR_CONST_PI*rday)/365 - phs_c0)
lsize = mct_avect_lsize(a2x)
do n = 1,lsize
a2x%rAttr(kz,n) = 10.0_R8
!--- correction to NCEP winds based on QSCAT ---
a2x%rAttr(ku,n) = a2x%rAttr(ku,n)*windFactor(n)
a2x%rAttr(kv,n) = a2x%rAttr(kv,n)*windFactor(n)
!--- density, tbot, & pslv taken directly from input stream, set pbot ---
! a2x%rAttr(kdens,n) = <copied from input streams bundle>
! a2x%rAttr(ktbot,n) = <copied from input streams bundle>
! a2x%rAttr(kpslv,n) = <copied from input streams bundle>
a2x%rAttr(kpbot,n) = a2x%rAttr(kpslv,n)
!--- correction to NCEP Arctic & Antarctic air T & potential T ---
if ( yc(n) < -60.0_R8 ) then
tMin = (avg_c0 + avg_c1*yc(n)) + (amp_c0 + amp_c1*yc(n))*cosFactor + tKFrz
a2x%rAttr(ktbot,n) = max(a2x%rAttr(ktbot,n), tMin)
else if ( yc(n) > 60.0_R8 ) then
factor = MIN(1.0_R8, 0.1_R8*(yc(n)-60.0_R8) )
a2x%rAttr(ktbot,n) = a2x%rAttr(ktbot,n) + factor * dTarc(mm)
endif
a2x%rAttr(kptem,n) = a2x%rAttr(ktbot,n)
!--- correction to NCEP relative humidity for heat budget balance ---
qsatT = 640380.0_R8/ exp(5107.4_R8/a2x%rAttr(ktbot,n))
a2x%rAttr(kshum,n) = a2x%rAttr(kshum,n) - &
(qsatT)*qsatFactor(n)/(100.0_R8*a2x%rAttr(kdens,n))
!-------------------------------------------------------------------------
! PRECIPITATION DATA
!-------------------------------------------------------------------------
avstrm%rAttr(sprec,n) = avstrm%rAttr(sprec,n)/86400.0_R8 ! convert mm/day to kg/m^2/s
avstrm%rAttr(sprec,n) = (avstrm%rAttr(sprec,n)*1.14168_R8)+7.44923e-07_R8 ! correction to GXGXS for water budget
a2x%rAttr(krc,n) = 0.0_R8 ! default zero
a2x%rAttr(ksc,n) = 0.0_R8
if (a2x%rAttr(ktbot,n) < tKFrz ) then ! assign precip to rain/snow components
a2x%rAttr(krl,n) = 0.0_R8
a2x%rAttr(ksl,n) = avstrm%rAttr(sprec,n)
else
a2x%rAttr(krl,n) = avstrm%rAttr(sprec,n)
a2x%rAttr(ksl,n) = 0.0_R8
endif
!-------------------------------------------------------------------------
! RADIATION DATA
!-------------------------------------------------------------------------
!--- fabricate required swdn components from net swdn ---
a2x%rAttr(kswvdr,n) = avstrm%rAttr(sswdn,n)*(0.28_R8)
a2x%rAttr(kswndr,n) = avstrm%rAttr(sswdn,n)*(0.31_R8)
a2x%rAttr(kswvdf,n) = avstrm%rAttr(sswdn,n)*(0.24_R8)
a2x%rAttr(kswndf,n) = avstrm%rAttr(sswdn,n)*(0.17_R8)
!--- compute net short-wave based on LY08 latitudinally-varying albedo ---
if (firstcall) then
a2x%rAttr(kswnet,n) = avstrm%rAttr(sswdn,n)-avstrm%rAttr(sswup,n)
else
avg_alb = (x2a%rAttr(kavsdr,n) + x2a%rAttr(kanidr,n) + &
x2a%rAttr(kavsdf,n) + x2a%rAttr(kanidf,n)) * 0.25_R8
a2x%rAttr(kswnet,n) = avstrm%rAttr(sswdn,n)*(1.0_R8 - avg_alb)
endif
!--- corrections to GISS sswdn for heat budget balancing ---
factor = 1.0_R8
if ( -60.0_R8 < yc(n) .and. yc(n) < -50.0_R8 ) then
factor = 1.0_R8 - (yc(n) + 60.0_R8)*(0.05_R8/10.0_R8)
else if ( -50.0_R8 < yc(n) .and. yc(n) < 30.0_R8 ) then
factor = 0.95_R8
else if ( 30.0_R8 < yc(n) .and. yc(n) < 40._R8 ) then
factor = 1.0_R8 - (40.0_R8 - yc(n))*(0.05_R8/10.0_R8)
endif
a2x%rAttr(kswnet,n) = a2x%rAttr(kswnet,n)*factor
a2x%rAttr(kswvdr,n) = a2x%rAttr(kswvdr,n)*factor
a2x%rAttr(kswndr,n) = a2x%rAttr(kswndr,n)*factor
a2x%rAttr(kswvdf,n) = a2x%rAttr(kswvdf,n)*factor
a2x%rAttr(kswndf,n) = a2x%rAttr(kswndf,n)*factor
!--- correction to GISS lwdn in Arctic ---
if ( yc(n) > 60._R8 ) then
factor = MIN(1.0_R8, 0.1_R8*(yc(n)-60.0_R8) )
a2x%rAttr(klwdn,n) = a2x%rAttr(klwdn,n) + factor * dLWarc
endif
enddo ! lsize
case('CORE2')
if (firstcall) then
if (sprec < 1 .or. sswdn < 1) then
write(logunit,F00) ' ERROR: prec and swdn must be in streams for CORE2'
call shr_sys_abort
(trim(subname)//' ERROR: prec and swdn must be in streams for CORE2')
endif
call datm_shr_CORE2getFactors
(factorFn,windFactor,winddFactor,qsatFactor, &
mpicom,compid,gsmap,ggrid,SDATM%nxg,SDATM%nyg)
endif
call shr_cal_date2eday
(currentYMD,eday)
rday = mod(eday,365) + real(currentTOD)/SHR_CONST_CDAY
cosfactor = cos((2.0_R8*SHR_CONST_PI*rday)/365 - phs_c0)
lsize = mct_avect_lsize(a2x)
do n = 1,lsize
a2x%rAttr(kz,n) = 10.0_R8
!--- correction to NCEP winds based on QSCAT ---
uprime = a2x%rAttr(ku,n)*windFactor(n)
vprime = a2x%rAttr(kv,n)*windFactor(n)
a2x%rAttr(ku,n) = uprime*cos(winddFactor(n)*degtorad)- &
vprime*sin(winddFactor(n)*degtorad)
a2x%rAttr(kv,n) = uprime*sin(winddFactor(n)*degtorad)+ &
vprime*cos(winddFactor(n)*degtorad)
!--- density, tbot, & pslv taken directly from input stream, set pbot ---
! a2x%rAttr(kdens,n) = <copied from input streams bundle>
! a2x%rAttr(ktbot,n) = <copied from input streams bundle>
! a2x%rAttr(kpslv,n) = <copied from input streams bundle>
a2x%rAttr(kpbot,n) = a2x%rAttr(kpslv,n)
!--- correction to NCEP Arctic & Antarctic air T & potential T ---
if ( yc(n) < -60.0_R8 ) then
tMin = (avg_c0 + avg_c1*yc(n)) + (amp_c0 + amp_c1*yc(n))*cosFactor + tKFrz
a2x%rAttr(ktbot,n) = max(a2x%rAttr(ktbot,n), tMin)
else if ( yc(n) > 60.0_R8 ) then
factor = MIN(1.0_R8, 0.1_R8*(yc(n)-60.0_R8) )
a2x%rAttr(ktbot,n) = a2x%rAttr(ktbot,n) + factor * dTarc(mm)
endif
a2x%rAttr(kptem,n) = a2x%rAttr(ktbot,n)
!--- correction to NCEP relative humidity for heat budget balance ---
a2x%rAttr(kshum,n) = a2x%rAttr(kshum,n) + qsatFactor(n)
!-------------------------------------------------------------------------
! PRECIPITATION DATA
!-------------------------------------------------------------------------
avstrm%rAttr(sprec,n) = avstrm%rAttr(sprec,n)/86400.0_R8 ! convert mm/day to kg/m^2/s
! only correct satellite products, do not correct Serreze Arctic data
if ( yc(n) < 58. ) then
avstrm%rAttr(sprec,n) = avstrm%rAttr(sprec,n)*1.14168_R8
endif
if ( yc(n) >= 58. .and. yc(n) < 68. ) then
factor = MAX(0.0_R8, 1.0_R8 - 0.1_R8*(yc(n)-58.0_R8) )
avstrm%rAttr(sprec,n) = avstrm%rAttr(sprec,n)*(factor*(1.14168_R8 - 1.0_R8) + 1.0_R8)
endif
a2x%rAttr(krc,n) = 0.0_R8 ! default zero
a2x%rAttr(ksc,n) = 0.0_R8
if (a2x%rAttr(ktbot,n) < tKFrz ) then ! assign precip to rain/snow components
a2x%rAttr(krl,n) = 0.0_R8
a2x%rAttr(ksl,n) = avstrm%rAttr(sprec,n)
else
a2x%rAttr(krl,n) = avstrm%rAttr(sprec,n)
a2x%rAttr(ksl,n) = 0.0_R8
endif
!-------------------------------------------------------------------------
! RADIATION DATA
!-------------------------------------------------------------------------
!--- fabricate required swdn components from net swdn ---
a2x%rAttr(kswvdr,n) = avstrm%rAttr(sswdn,n)*(0.28_R8)
a2x%rAttr(kswndr,n) = avstrm%rAttr(sswdn,n)*(0.31_R8)
a2x%rAttr(kswvdf,n) = avstrm%rAttr(sswdn,n)*(0.24_R8)
a2x%rAttr(kswndf,n) = avstrm%rAttr(sswdn,n)*(0.17_R8)
!--- compute net short-wave based on LY08 latitudinally-varying albedo ---
avg_alb = ( 0.069 - 0.011*cos(2.0_R8*yc(n)*degtorad ) )
a2x%rAttr(kswnet,n) = avstrm%rAttr(sswdn,n)*(1.0_R8 - avg_alb)
!--- corrections to GISS sswdn for heat budget balancing ---
factor = 1.0_R8
if ( -60.0_R8 < yc(n) .and. yc(n) < -50.0_R8 ) then
factor = 1.0_R8 - (yc(n) + 60.0_R8)*(0.05_R8/10.0_R8)
else if ( -50.0_R8 < yc(n) .and. yc(n) < 30.0_R8 ) then
factor = 0.95_R8
else if ( 30.0_R8 < yc(n) .and. yc(n) < 40._R8 ) then
factor = 1.0_R8 - (40.0_R8 - yc(n))*(0.05_R8/10.0_R8)
endif
a2x%rAttr(kswnet,n) = a2x%rAttr(kswnet,n)*factor
a2x%rAttr(kswvdr,n) = a2x%rAttr(kswvdr,n)*factor
a2x%rAttr(kswndr,n) = a2x%rAttr(kswndr,n)*factor
a2x%rAttr(kswvdf,n) = a2x%rAttr(kswvdf,n)*factor
a2x%rAttr(kswndf,n) = a2x%rAttr(kswndf,n)*factor
!--- correction to GISS lwdn in Arctic ---
if ( yc(n) > 60._R8 ) then
factor = MIN(1.0_R8, 0.1_R8*(yc(n)-60.0_R8) )
a2x%rAttr(klwdn,n) = a2x%rAttr(klwdn,n) + factor * dLWarc
endif
enddo ! lsize
case('CLMNCEP')
if (firstcall) then
if (swind < 1 .or. stbot < 1) then
write(logunit,F00) ' ERROR: wind and tbot must be in streams for CLMNCEP'
call shr_sys_abort
(trim(subname)//' ERROR: wind and tbot must be in streams for CLMNCEP')
endif
rtmp = maxval(a2x%rAttr(ktbot,:))
call shr_mpi_max(rtmp,tbotmax,mpicom,'datm_tbot',all=.true.)
rtmp = maxval(x2a%rAttr(kanidr,:))
call shr_mpi_max(rtmp,anidrmax,mpicom,'datm_ani',all=.true.)
if (stdew > 0) then
rtmp = maxval(avstrm%rAttr(stdew,:))
call shr_mpi_max(rtmp,tdewmax,mpicom,'datm_tdew',all=.true.)
endif
if (my_task == master_task) &
write(logunit,*) trim(subname),' max values = ',tbotmax,tdewmax,anidrmax
endif
lsize = mct_avect_lsize(a2x)
do n = 1,SDATM%nstreams
call shr_dmodel_translateAV
(SDATM%avs(n),avstrm,stifld,stofld,rearr)
enddo
do n = 1,lsize
!--- bottom layer height ---
if (sz < 1) a2x%rAttr(kz,n) = 30.0_R8
!--- temperature ---
if (tbotmax < 50.0_R8) a2x%rAttr(ktbot,n) = a2x%rAttr(ktbot,n) + tkFrz
a2x%rAttr(kptem,n) = a2x%rAttr(ktbot,n)
!--- pressure ---
if (spbot < 1) a2x%rAttr(kpbot,n) = pstd
a2x%rAttr(kpslv,n) = a2x%rAttr(kpbot,n)
!--- u, v wind velocity ---
a2x%rAttr(ku,n) = avstrm%rAttr(swind,n)/sqrt(2.0_R8)
a2x%rAttr(kv,n) = a2x%rAttr(ku,n)
!--- specific humidity ---
tbot = a2x%rAttr(ktbot,n)
pbot = a2x%rAttr(kpbot,n)
if (sshum > 0) then
e = datm_shr_esat
(tbot,tbot)
qsat = (0.622_R8 * e)/(pbot - 0.378_R8 * e)
if (qsat < a2x%rAttr(kshum,n)) then
a2x%rAttr(kshum,n) = qsat
endif
else if (srh > 0) then
e = avstrm%rAttr(srh,n) * 0.01_R8 * datm_shr_esat
(tbot,tbot)
qsat = (0.622_R8 * e)/(pbot - 0.378_R8 * e)
a2x%rAttr(kshum,n) = qsat
else if (stdew > 0) then
if (tdewmax < 50.0_R8) avstrm%rAttr(stdew,n) = avstrm%rAttr(stdew,n) + tkFrz
e = datm_shr_esat
(avstrm%rAttr(stdew,n),tbot)
qsat = (0.622_R8 * e)/(pbot - 0.378_R8 * e)
a2x%rAttr(kshum,n) = qsat
else
call shr_sys_abort
(subname//'ERROR: cannot compute shum')
endif
!--- density ---
vp = (a2x%rAttr(kshum,n)*pbot) / (0.622_R8 + 0.0378_R8 * a2x%rAttr(kshum,n))
a2x%rAttr(kdens,n) = (pbot - 0.0378_R8 * vp) / (tbot*rdair)
!--- downward longwave ---
if (slwdn < 1) then
e = a2x%rAttr(kpslv,n) * a2x%rAttr(kshum,n) / (0.622_R8 + 0.378_R8 * a2x%rAttr(kshum,n))
ea = 0.70_R8 + 5.95e-05_R8 * 0.01_R8 * e * exp(1500.0_R8/tbot)
a2x%rAttr(klwdn,n) = ea * stebol * tbot**4
endif
!--- shortwave radiation ---
if (sswdndf > 0 .and. sswdndr > 0) then
a2x%rAttr(kswndr,n) = avstrm%rAttr(sswdndr,n) * 0.50_R8
a2x%rAttr(kswvdr,n) = avstrm%rAttr(sswdndr,n) * 0.50_R8
a2x%rAttr(kswndf,n) = avstrm%rAttr(sswdndf,n) * 0.50_R8
a2x%rAttr(kswvdf,n) = avstrm%rAttr(sswdndf,n) * 0.50_R8
elseif (sswdn > 0) then
! relationship between incoming NIR or VIS radiation and ratio of
! direct to diffuse radiation calculated based on one year's worth of
! hourly CAM output from CAM version cam3_5_55
swndr = avstrm%rAttr(sswdn,n) * 0.50_R8
ratio_rvrf = min(0.99_R8,max(0.29548_R8 + 0.00504_R8*swndr &
-1.4957e-05_R8*swndr**2 + 1.4881e-08_R8*swndr**3,0.01_R8))
a2x%rAttr(kswndr,n) = ratio_rvrf*swndr
swndf = avstrm%rAttr(sswdn,n) * 0.50_R8
a2x%rAttr(kswndf,n) = (1._R8 - ratio_rvrf)*swndf
swvdr = avstrm%rAttr(sswdn,n) * 0.50_R8
ratio_rvrf = min(0.99_R8,max(0.17639_R8 + 0.00380_R8*swvdr &
-9.0039e-06_R8*swvdr**2 + 8.1351e-09_R8*swvdr**3,0.01_R8))
a2x%rAttr(kswvdr,n) = ratio_rvrf*swvdr
swvdf = avstrm%rAttr(sswdn,n) * 0.50_R8
a2x%rAttr(kswvdf,n) = (1._R8 - ratio_rvrf)*swvdf
else
call shr_sys_abort
(subName//'ERROR: cannot compute short-wave down')
endif
!--- swnet: a diagnostic quantity ---
if (anidrmax < 1.0e-8 .or. anidrmax > SHR_CONST_SPVAL * 0.9_R8) then
a2x%rAttr(kswnet,n) = 0.0_R8
else
a2x%rAttr(kswnet,n) = (1.0_R8-x2a%rAttr(kanidr,n))*a2x%rAttr(kswndr,n) + &
(1.0_R8-x2a%rAttr(kavsdr,n))*a2x%rAttr(kswvdr,n) + &
(1.0_R8-x2a%rAttr(kanidf,n))*a2x%rAttr(kswndf,n) + &
(1.0_R8-x2a%rAttr(kavsdf,n))*a2x%rAttr(kswvdf,n)
endif
!--- rain and snow ---
if (sprecc > 0 .and. sprecl > 0) then
a2x%rAttr(krc,n) = avstrm%rAttr(sprecc,n)
a2x%rAttr(krl,n) = avstrm%rAttr(sprecl,n)
elseif (sprecn > 0) then
a2x%rAttr(krc,n) = avstrm%rAttr(sprecn,n)*0.1_R8
a2x%rAttr(krl,n) = avstrm%rAttr(sprecn,n)*0.9_R8
else
call shr_sys_abort
(subName//'ERROR: cannot compute rain and snow')
endif
!--- split precip between rain & snow ---
!--- note: aribitrarily small negative values cause CLM to crash ---
frac = (tbot - tkFrz)*0.5_R8 ! ramp near freezing
frac = min(1.0_R8,max(0.0_R8,frac)) ! bound in [0,1]
a2x%rAttr(ksc,n) = max(0.0_R8, a2x%rAttr(krc,n)*(1.0_R8 - frac) )
a2x%rAttr(ksl,n) = max(0.0_R8, a2x%rAttr(krl,n)*(1.0_R8 - frac) )
a2x%rAttr(krc,n) = max(0.0_R8, a2x%rAttr(krc,n)*( frac) )
a2x%rAttr(krl,n) = max(0.0_R8, a2x%rAttr(krl,n)*( frac) )
enddo
end select
call t_stopf('datm_mode')
if (write_restart) then
call t_startf('datm_restart')
call seq_infodata_GetData
( infodata, case_name=case_name)
write(rest_file,"(2a,i4.4,a,i2.2,a,i2.2,a,i5.5,a)") &
trim(case_name), '.datm.r.', yy,'-',mm,'-',dd,'-',currentTOD,'.nc'
write(rest_file_strm,"(2a,i4.4,a,i2.2,a,i2.2,a,i5.5,a)") &
trim(case_name), '.datm.rs1.', yy,'-',mm,'-',dd,'-',currentTOD,'.bin'
if (my_task == master_task) then
nu = shr_file_getUnit
()
open(nu,file=trim(rpfile),form='formatted')
write(nu,'(a)') rest_file
write(nu,'(a)') rest_file_strm
close(nu)
call shr_file_freeUnit
(nu)
endif
! if (my_task == master_task) write(logunit,F04) ' writing ',trim(rest_file),currentYMD,currentTOD
! call shr_pcdf_readwrite('write',trim(rest_file),mpicom,gsmap,clobber=.true., &
! rf1=somtp,rf1n='somtp')
if (my_task == master_task) write(logunit,F04) ' writing ',trim(rest_file_strm),currentYMD,currentTOD
call shr_strdata_restWrite
(trim(rest_file_strm),SDATM,mpicom,trim(case_name),'SDATM strdata')
call shr_sys_flush
(logunit)
call t_stopf('datm_restart')
endif
call t_stopf('datm')
!----------------------------------------------------------------------------
! Log output for model date
! Reset shr logging to original values
!----------------------------------------------------------------------------
call t_startf('datm_run2')
if (my_task == master_task) then
write(logunit,F04) trim(myModelName),': model date ', CurrentYMD,CurrentTOD
call shr_sys_flush
(logunit)
end if
firstcall = .false.
call shr_file_setLogUnit
(shrlogunit)
call shr_file_setLogLevel
(shrloglev)
call shr_sys_flush
(logunit)
call t_stopf('datm_run2')
call t_stopf('DATM_RUN')
end subroutine datm_comp_run
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: datm_comp_final
!
! !DESCRIPTION:
! finalize method for dead atm model
!
! !REVISION HISTORY:
!
! !INTERFACE: ------------------------------------------------------------------
!
subroutine datm_comp_final() 1
implicit none
!EOP
!--- formats ---
character(*), parameter :: F00 = "('(datm_comp_final) ',8a)"
character(*), parameter :: F91 = "('(datm_comp_final) ',73('-'))"
character(*), parameter :: subName = "(datm_comp_final) "
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
call t_startf('DATM_FINAL')
if (my_task == master_task) then
write(logunit,F91)
write(logunit,F00) trim(myModelName),': end of main integration loop'
write(logunit,F91)
end if
call t_stopf('DATM_FINAL')
end subroutine datm_comp_final
!===============================================================================
!===============================================================================
end module datm_comp_mod