diff --git a/datm/CMakeLists.txt b/datm/CMakeLists.txt
index b72fd41bdf..61785d7d1c 100644
--- a/datm/CMakeLists.txt
+++ b/datm/CMakeLists.txt
@@ -3,7 +3,8 @@ project(datm Fortran)
add_library(datm atm_comp_nuopc.F90
datm_datamode_clmncep_mod.F90
datm_datamode_core2_mod.F90
- datm_datamode_jra_mod.F90)
+ datm_datamode_jra_mod.F90
+ datm_datamode_era5_mod.F90)
add_dependencies(datm dshr streams)
target_include_directories (datm PUBLIC ${ESMF_F90COMPILEPATHS})
diff --git a/datm/atm_comp_nuopc.F90 b/datm/atm_comp_nuopc.F90
index 22095cdd71..2801a50e07 100644
--- a/datm/atm_comp_nuopc.F90
+++ b/datm/atm_comp_nuopc.F90
@@ -43,6 +43,11 @@ module atm_comp_nuopc
use datm_datamode_clmncep_mod , only : datm_datamode_clmncep_advance
use datm_datamode_clmncep_mod , only : datm_datamode_clmncep_restart_write
use datm_datamode_clmncep_mod , only : datm_datamode_clmncep_restart_read
+ use datm_datamode_era5_mod , only : datm_datamode_era5_advertise
+ use datm_datamode_era5_mod , only : datm_datamode_era5_init_pointers
+ use datm_datamode_era5_mod , only : datm_datamode_era5_advance
+ use datm_datamode_era5_mod , only : datm_datamode_era5_restart_write
+ use datm_datamode_era5_mod , only : datm_datamode_era5_restart_read
implicit none
private ! except
@@ -275,7 +280,8 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc)
if ( trim(datamode) == 'CORE2_NYF' .or. &
trim(datamode) == 'CORE2_IAF' .or. &
trim(datamode) == 'CORE_IAF_JRA' .or. &
- trim(datamode) == 'CLMNCEP') then
+ trim(datamode) == 'CLMNCEP' .or. &
+ trim(datamode) == 'ERA5') then
else
call shr_sys_abort(' ERROR illegal datm datamode = '//trim(datamode))
endif
@@ -293,6 +299,9 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc)
call datm_datamode_clmncep_advertise(exportState, fldsExport, flds_scalar_name, &
flds_co2, flds_wiso, flds_presaero, rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ case ('ERA5')
+ call datm_datamode_era5_advertise(exportState, fldsExport, flds_scalar_name, rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
end select
end subroutine InitializeAdvertise
@@ -528,6 +537,9 @@ subroutine datm_comp_run(importState, exportState, target_ymd, target_tod, targe
case('CLMNCEP')
call datm_datamode_clmncep_init_pointers(importState, exportState, sdat, rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ case('ERA5')
+ call datm_datamode_era5_init_pointers(exportState, sdat, rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
end select
! Read restart if needed
@@ -539,6 +551,8 @@ subroutine datm_comp_run(importState, exportState, target_ymd, target_tod, targe
call datm_datamode_jra_restart_read(restfilm, inst_suffix, logunit, my_task, mpicom, sdat)
case('CLMNCEP')
call datm_datamode_clmncep_restart_read(restfilm, inst_suffix, logunit, my_task, mpicom, sdat)
+ case('ERA5')
+ call datm_datamode_era5_restart_read(restfilm, inst_suffix, logunit, my_task, mpicom, sdat)
end select
end if
@@ -581,6 +595,10 @@ subroutine datm_comp_run(importState, exportState, target_ymd, target_tod, targe
case('CLMNCEP')
call datm_datamode_clmncep_advance(importstate, exportstate, masterproc, logunit, mpicom, rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ case('ERA5')
+ call datm_datamode_era5_advance(exportstate, masterproc, logunit, mpicom, target_ymd, &
+ target_tod, sdat%model_calendar, rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
end select
! Write restarts if needed
@@ -598,6 +616,10 @@ subroutine datm_comp_run(importState, exportState, target_ymd, target_tod, targe
call datm_datamode_clmncep_restart_write(case_name, inst_suffix, target_ymd, target_tod, &
logunit, mpicom, my_task, sdat)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ case('ERA5')
+ call datm_datamode_era5_restart_write(case_name, inst_suffix, target_ymd, target_tod, &
+ logunit, mpicom, my_task, sdat)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
end select
end if
@@ -606,7 +628,7 @@ subroutine datm_comp_run(importState, exportState, target_ymd, target_tod, targe
! Diagnostics
if (diagnose_data) then
- call dshr_state_diagnose(exportState, flds_scalar_name, subname//':ES',rc=rc)
+ call dshr_state_diagnose(exportState, flds_scalar_name, subname//':ES', rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
end if
diff --git a/datm/cime_config/config_component.xml b/datm/cime_config/config_component.xml
index c9448a0d15..1c0522bf87 100644
--- a/datm/cime_config/config_component.xml
+++ b/datm/cime_config/config_component.xml
@@ -10,7 +10,7 @@
This file may have atm desc entries.
-->
- Data driven ATM
+ Data driven ATM
QIAN data set
QIAN with water isotopes
CRUNCEP data set
@@ -23,6 +23,7 @@
COREv2 interannual forcing
interannual JRA55 forcing
interannual JRA55 forcing, v1.4, through 2018
+ ERA5 interannual forcing
@@ -36,7 +37,7 @@
char
- CORE2_NYF,CORE2_IAF,CLM_QIAN,CLM_QIAN_WISO,CLM1PT,CLMCRUNCEP,CLMCRUNCEPv7,CLMGSWP3v1,CLMNLDAS2,CPLHIST,CORE_IAF_JRA,CORE_IAF_JRA_1p4_2018
+ CORE2_NYF,CORE2_IAF,CLM_QIAN,CLM_QIAN_WISO,CLM1PT,CLMCRUNCEP,CLMCRUNCEPv7,CLMGSWP3v1,CLMNLDAS2,CPLHIST,CORE_IAF_JRA,CORE_IAF_JRA_1p4_2018,ERA5
CORE2_NYF
run_component_datm
env_run.xml
@@ -56,6 +57,7 @@
CLMNLDAS2
CLM1PT
CPLHIST
+ ERA5
diff --git a/datm/cime_config/namelist_definition_datm.xml b/datm/cime_config/namelist_definition_datm.xml
index 6b8360039e..77bcbb4210 100644
--- a/datm/cime_config/namelist_definition_datm.xml
+++ b/datm/cime_config/namelist_definition_datm.xml
@@ -30,6 +30,7 @@
CORE2_IAF = CORE2 intra-annual year forcing (for forcing POP and CICE)
CORE_IAF_JRA = JRA55 intra-annual year forcing (for forcing POP and CICE)
CORE_IAF_JRA_1p4_2018 = JRA55 intra-annual year forcing, v1.4, through 2018 (for forcing POP and CICE)
+ ERA5 = ERA5 intra-annual year forcing
CPLHIST = Streams for lnd or ocn/ice forcing used for spinup
Currently the following optional streams are supported
@@ -239,6 +240,9 @@
CORE2_IAF.NCEP.DENS.SOFS,CORE2_IAF.NCEP.PSLV.SOFS,CORE2_IAF.PREC.SOFS.DAILY,CORE2_IAF.LWDN.SOFS.DAILY,CORE2_IAF.SWDN.SOFS.DAILY,CORE2_IAF.SWUP.SOFS.DAILY,CORE2_IAF.SHUM.SOFS.6HOUR,CORE2_IAF.TBOT.SOFS.6HOUR,CORE2_IAF.U.SOFS.6HOUR,CORE2_IAF.V.SOFS.6HOUR,CORE2_IAF.CORE2.ArcFactor
+
+ ERA5_HOURLY
+
CPLHISTForcing.Solar,CPLHISTForcing.nonSolarFlux,CPLHISTForcing.State3hr,CPLHISTForcing.State1hr
@@ -440,6 +444,12 @@
$DIN_LOC_ROOT/share/meshes/T62_040121_ESMFmesh_c20190714.nc
+
+
+
+
+ $DIN_LOC_ROOT/share/meshes/TL639_200618_ESMFmesh.nc
+
@@ -1763,6 +1773,23 @@
$DIN_LOC_ROOT/atm/datm7/CORE2/CORE2.t_10.ArcFactor.T62.1997-2004.nc
+
+
+
+ $DIN_LOC_ROOT/atm/datm7/ERA5/ERA5.TL639.2019.01.200618.nc
+ $DIN_LOC_ROOT/atm/datm7/ERA5/ERA5.TL639.2019.02.200618.nc
+ $DIN_LOC_ROOT/atm/datm7/ERA5/ERA5.TL639.2019.03.200618.nc
+ $DIN_LOC_ROOT/atm/datm7/ERA5/ERA5.TL639.2019.04.200618.nc
+ $DIN_LOC_ROOT/atm/datm7/ERA5/ERA5.TL639.2019.05.200618.nc
+ $DIN_LOC_ROOT/atm/datm7/ERA5/ERA5.TL639.2019.06.200618.nc
+ $DIN_LOC_ROOT/atm/datm7/ERA5/ERA5.TL639.2019.07.200618.nc
+ $DIN_LOC_ROOT/atm/datm7/ERA5/ERA5.TL639.2019.08.200618.nc
+ $DIN_LOC_ROOT/atm/datm7/ERA5/ERA5.TL639.2019.09.200618.nc
+ $DIN_LOC_ROOT/atm/datm7/ERA5/ERA5.TL639.2019.10.200618.nc
+ $DIN_LOC_ROOT/atm/datm7/ERA5/ERA5.TL639.2019.11.200618.nc
+ $DIN_LOC_ROOT/atm/datm7/ERA5/ERA5.TL639.2019.12.200618.nc
+
+
@@ -2172,6 +2199,32 @@
TarcFactor tarcf
+
+
+
+
+ u10 Sa_u
+ v10 Sa_v
+ t2m Sa_tbot
+ d2m Sa_tdew
+ msl Sa_pslv
+ sp Sa_pbot
+ tp Faxa_rain
+ cp Faxa_rainc
+ lsp Faxa_rainl
+ csf Faxa_snowc
+ lsf Faxa_snowl
+ ssrd Faxa_swdn
+ strd Faxa_lwdn
+ aluvp Faxa_swvdr
+ aluvd Faxa_swvdf
+ alnip Faxa_swndr
+ alnid Faxa_swndf
+ sshf Faxa_sen
+ slhf Faxa_lat
+ ewss Faxa_taux
+ nsss Faxa_tauy
+
@@ -2285,6 +2338,7 @@
1
1
1
+ 1900
1850
2015
1979
@@ -2347,6 +2401,7 @@
1958
1958
1958
+ 2019
1850
2015
2006
@@ -2407,6 +2462,7 @@
2016
2016
2016
+ 2019
2014
2500
2012
@@ -2600,6 +2656,7 @@
u:v
u:v
u:v
+ u:v,taux:tauy
@@ -2630,7 +2687,7 @@
char
datm
datm_nml
- CLMNCEP,COPYALL,CORE2_NYF,CORE2_IAF,CORE_IAF_JRA
+ CLMNCEP,COPYALL,CORE2_NYF,CORE2_IAF,CORE_IAF_JRA,ERA5
general method that operates on the data. this is generally
implemented in the data models but is set in the strdata method for
@@ -2669,6 +2726,8 @@
mode replicates code previously found in CLM (circa 2005), before the
LMWG started using the CCSM flux coupler and data models to do
active-land-only simulations.
+ datamode = "ERA5"
+ Fifth generation ECMWF atmospheric reanalysis of the global climate
COPYALL
@@ -2676,6 +2735,7 @@
CORE2_NYF
CORE2_IAF
CORE_IAF_JRA
+ ERA5
COPYALL
diff --git a/datm/datm_datamode_era5_mod.F90 b/datm/datm_datamode_era5_mod.F90
new file mode 100644
index 0000000000..6c924d101d
--- /dev/null
+++ b/datm/datm_datamode_era5_mod.F90
@@ -0,0 +1,379 @@
+module datm_datamode_era5_mod
+
+ use ESMF
+ use NUOPC , only : NUOPC_Advertise
+ use shr_kind_mod , only : r8=>shr_kind_r8, i8=>shr_kind_i8, cl=>shr_kind_cl, cs=>shr_kind_cs
+ use shr_sys_mod , only : shr_sys_abort
+ use shr_precip_mod , only : shr_precip_partition_rain_snow_ramp
+ use shr_mpi_mod , only : shr_mpi_max
+ use shr_const_mod , only : shr_const_tkfrz, shr_const_rhofw, shr_const_rdair
+ use dshr_methods_mod , only : dshr_state_getfldptr, chkerr
+ use dshr_strdata_mod , only : shr_strdata_type, shr_strdata_get_stream_pointer
+ use dshr_mod , only : dshr_restart_read, dshr_restart_write
+ use dshr_strdata_mod , only : shr_strdata_type
+ use dshr_fldlist_mod , only : fldlist_type, dshr_fldlist_add
+
+ implicit none
+ private ! except
+
+ public :: datm_datamode_era5_advertise
+ public :: datm_datamode_era5_init_pointers
+ public :: datm_datamode_era5_advance
+ public :: datm_datamode_era5_restart_write
+ public :: datm_datamode_era5_restart_read
+ private :: datm_eSat ! determine saturation vapor pressure
+
+ ! export state data
+ real(r8), pointer :: Sa_z(:) => null()
+ real(r8), pointer :: Sa_u(:) => null()
+ real(r8), pointer :: Sa_v(:) => null()
+ real(r8), pointer :: Sa_tbot(:) => null()
+ real(r8), pointer :: Sa_ptem(:) => null()
+ real(r8), pointer :: Sa_shum(:) => null()
+ real(r8), pointer :: Sa_dens(:) => null()
+ real(r8), pointer :: Sa_pbot(:) => null()
+ real(r8), pointer :: Sa_pslv(:) => null()
+ real(r8), pointer :: Faxa_lwdn(:) => null()
+ real(r8), pointer :: Faxa_rain(:) => null()
+ real(r8), pointer :: Faxa_rainc(:) => null()
+ real(r8), pointer :: Faxa_rainl(:) => null()
+ real(r8), pointer :: Faxa_snowc(:) => null()
+ real(r8), pointer :: Faxa_snowl(:) => null()
+ real(r8), pointer :: Faxa_swndr(:) => null()
+ real(r8), pointer :: Faxa_swndf(:) => null()
+ real(r8), pointer :: Faxa_swvdr(:) => null()
+ real(r8), pointer :: Faxa_swvdf(:) => null()
+ real(r8), pointer :: Faxa_swnet(:) => null()
+ real(r8), pointer :: Faxa_swdn(:) => null()
+ real(r8), pointer :: Faxa_sen(:) => null()
+ real(r8), pointer :: Faxa_lat(:) => null()
+ real(r8), pointer :: Faxa_taux(:) => null()
+ real(r8), pointer :: Faxa_tauy(:) => null()
+
+ ! stream data
+ real(r8), pointer :: strm_tdew(:) => null()
+
+ logical :: atm_prognostic = .false.
+ real(r8) :: tbotmax ! units detector
+ real(r8) :: tdewmax ! units detector
+
+ real(r8) , parameter :: tKFrz = SHR_CONST_TKFRZ
+ real(r8) , parameter :: rdair = SHR_CONST_RDAIR ! dry air gas constant ~ J/K/kg
+ real(r8) , parameter :: rhofw = SHR_CONST_RHOFW ! density of fresh water ~ kg/m^3
+
+ character(*), parameter :: nullstr = 'undefined'
+ character(*), parameter :: rpfile = 'rpointer.atm'
+ character(*), parameter :: u_FILE_u = &
+ __FILE__
+
+!===============================================================================
+contains
+!===============================================================================
+
+ subroutine datm_datamode_era5_advertise(exportState, fldsexport, &
+ flds_scalar_name, rc)
+
+ ! input/output variables
+ type(esmf_State) , intent(inout) :: exportState
+ type(fldlist_type) , pointer :: fldsexport
+ character(len=*) , intent(in) :: flds_scalar_name
+ integer , intent(out) :: rc
+
+ ! local variables
+ type(fldlist_type), pointer :: fldList
+ !-------------------------------------------------------------------------------
+
+ rc = ESMF_SUCCESS
+
+ call dshr_fldList_add(fldsExport, trim(flds_scalar_name))
+ call dshr_fldList_add(fldsExport, 'Sa_z' )
+ call dshr_fldList_add(fldsExport, 'Sa_u' )
+ call dshr_fldList_add(fldsExport, 'Sa_v' )
+ call dshr_fldList_add(fldsExport, 'Sa_tbot' )
+ call dshr_fldList_add(fldsExport, 'Sa_ptem' )
+ call dshr_fldList_add(fldsExport, 'Sa_dens' )
+ call dshr_fldList_add(fldsExport, 'Sa_pslv' )
+ call dshr_fldList_add(fldsExport, 'Sa_pbot' )
+ call dshr_fldList_add(fldsExport, 'Sa_shum' )
+ call dshr_fldList_add(fldsExport, 'Faxa_rain' )
+ call dshr_fldList_add(fldsExport, 'Faxa_rainc' )
+ call dshr_fldList_add(fldsExport, 'Faxa_rainl' )
+ call dshr_fldList_add(fldsExport, 'Faxa_snowc' )
+ call dshr_fldList_add(fldsExport, 'Faxa_snowl' )
+ call dshr_fldList_add(fldsExport, 'Faxa_swndr' )
+ call dshr_fldList_add(fldsExport, 'Faxa_swvdr' )
+ call dshr_fldList_add(fldsExport, 'Faxa_swndf' )
+ call dshr_fldList_add(fldsExport, 'Faxa_swvdf' )
+ call dshr_fldList_add(fldsExport, 'Faxa_swnet' )
+ call dshr_fldList_add(fldsExport, 'Faxa_lwdn' )
+ call dshr_fldList_add(fldsExport, 'Faxa_swdn' )
+ call dshr_fldList_add(fldsExport, 'Faxa_sen' )
+ call dshr_fldList_add(fldsExport, 'Faxa_lat' )
+ call dshr_fldList_add(fldsExport, 'Faxa_taux' )
+ call dshr_fldList_add(fldsExport, 'Faxa_tauy' )
+
+ fldlist => fldsExport ! the head of the linked list
+ do while (associated(fldlist))
+ call NUOPC_Advertise(exportState, standardName=fldlist%stdname, rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ call ESMF_LogWrite('(datm_comp_advertise): Fr_atm'//trim(fldList%stdname), ESMF_LOGMSG_INFO)
+ fldList => fldList%next
+ enddo
+
+ end subroutine datm_datamode_era5_advertise
+
+ !===============================================================================
+ subroutine datm_datamode_era5_init_pointers(exportState, sdat, rc)
+
+ ! input/output variables
+ type(ESMF_State) , intent(inout) :: exportState
+ type(shr_strdata_type) , intent(in) :: sdat
+ integer , intent(out) :: rc
+
+ ! local variables
+ type(ESMF_StateItem_Flag) :: itemFlag
+ character(len=*), parameter :: subname='(datm_init_pointers): '
+ !-------------------------------------------------------------------------------
+
+ rc = ESMF_SUCCESS
+
+ ! initialize pointers for module level stream arrays
+ call shr_strdata_get_stream_pointer( sdat, 'Sa_tdew' , strm_tdew , rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+
+ ! get export state pointers
+ call dshr_state_getfldptr(exportState, 'Sa_z' , fldptr1=Sa_z , rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ call dshr_state_getfldptr(exportState, 'Sa_tbot' , fldptr1=Sa_tbot , rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ call dshr_state_getfldptr(exportState, 'Sa_pbot' , fldptr1=Sa_pbot , rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ call dshr_state_getfldptr(exportState, 'Sa_ptem' , fldptr1=Sa_ptem , rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ call dshr_state_getfldptr(exportState, 'Sa_shum' , fldptr1=Sa_shum , rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ call dshr_state_getfldptr(exportState, 'Sa_dens' , fldptr1=Sa_dens , rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ call dshr_state_getfldptr(exportState, 'Faxa_rain' , fldptr1=Faxa_rain , rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ call dshr_state_getfldptr(exportState, 'Faxa_rainc' , fldptr1=Faxa_rainc , rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ call dshr_state_getfldptr(exportState, 'Faxa_rainl' , fldptr1=Faxa_rainl , rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ call dshr_state_getfldptr(exportState, 'Faxa_snowc' , fldptr1=Faxa_snowc , rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ call dshr_state_getfldptr(exportState, 'Faxa_snowl' , fldptr1=Faxa_snowl , rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ call dshr_state_getfldptr(exportState, 'Faxa_swvdr' , fldptr1=Faxa_swvdr , rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ call dshr_state_getfldptr(exportState, 'Faxa_swvdf' , fldptr1=Faxa_swvdf , rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ call dshr_state_getfldptr(exportState, 'Faxa_swndr' , fldptr1=Faxa_swndr , rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ call dshr_state_getfldptr(exportState, 'Faxa_swndf' , fldptr1=Faxa_swndf , rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ call dshr_state_getfldptr(exportState, 'Faxa_swnet' , fldptr1=Faxa_swnet , rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ call dshr_state_getfldptr(exportState, 'Faxa_swdn' , fldptr1=Faxa_swdn , rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ call dshr_state_getfldptr(exportState, 'Faxa_lwdn' , fldptr1=Faxa_lwdn , rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ call dshr_state_getfldptr(exportState, 'Faxa_sen' , fldptr1=Faxa_sen , rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ call dshr_state_getfldptr(exportState, 'Faxa_lat' , fldptr1=Faxa_lat , rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ call dshr_state_getfldptr(exportState, 'Faxa_taux' , fldptr1=Faxa_taux , rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ call dshr_state_getfldptr(exportState, 'Faxa_tauy' , fldptr1=Faxa_tauy , rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+
+ end subroutine datm_datamode_era5_init_pointers
+
+ !===============================================================================
+ subroutine datm_datamode_era5_advance(exportstate, masterproc, logunit, mpicom, target_ymd, target_tod, model_calendar, rc)
+
+ ! input/output variables
+ type(ESMF_State) , intent(inout) :: exportState
+ logical , intent(in) :: masterproc
+ integer , intent(in) :: logunit
+ integer , intent(in) :: mpicom
+ integer , intent(in) :: target_ymd
+ integer , intent(in) :: target_tod
+ character(len=*) , intent(in) :: model_calendar
+ integer , intent(out) :: rc
+
+ ! local variables
+ logical :: first_time = .true.
+ integer :: n,kf ! indices
+ integer :: lsize ! size of attr vect
+ real(r8) :: rtmp
+ real(r8) :: swndr
+ real(r8) :: swndf
+ real(r8) :: swvdr
+ real(r8) :: swvdf
+ real(r8) :: ratio_rvrf
+ real(r8) :: tbot, pbot
+ real(r8) :: vp
+ real(r8) :: ea, e, qsat, frac
+ character(len=*), parameter :: subname='(datm_datamode_era5_advance): '
+ !-------------------------------------------------------------------------------
+
+ rc = ESMF_SUCCESS
+
+ lsize = size(strm_tdew)
+
+ if (first_time) then
+ ! determine tbotmax (see below for use)
+ rtmp = maxval(Sa_tbot(:))
+ call shr_mpi_max(rtmp, tbotmax, mpicom, 'datm_tbot', all=.true.)
+ if (masterproc) write(logunit,*) trim(subname),' tbotmax = ',tbotmax
+
+ ! determine tdewmax (see below for use)
+ rtmp = maxval(strm_tdew(:))
+ call shr_mpi_max(rtmp, tdewmax, mpicom, 'datm_tdew', all=.true.)
+ if (masterproc) write(logunit,*) trim(subname),' tdewmax = ',tdewmax
+
+ ! reset first_time
+ first_time = .false.
+ end if
+
+ do n = 1, lsize
+ !--- bottom layer height ---
+ Sa_z(n) = 10.0_r8
+
+ !--- temperature ---
+ if (tbotmax < 50.0_r8) Sa_tbot(n) = Sa_tbot(n) + tkFrz
+ ! Limit very cold forcing to 180K
+ Sa_tbot(n) = max(180._r8, Sa_tbot(n))
+ Sa_ptem(n) = Sa_tbot(n)
+
+ !--- specific humidity ---
+ tbot = Sa_tbot(n)
+ pbot = Sa_pbot(n)
+ if (tdewmax < 50.0_r8) strm_tdew(n) = strm_tdew(n) + tkFrz
+ e = datm_eSat(strm_tdew(n),tbot)
+ qsat = (0.622_r8 * e)/(pbot - 0.378_r8 * e)
+ Sa_shum(n) = qsat
+
+ !--- density ---
+ vp = (Sa_shum(n)*pbot) / (0.622_r8 + 0.378_r8 * Sa_shum(n))
+ Sa_dens(n) = (pbot - 0.378_r8 * vp) / (tbot*rdair)
+
+ !--- shortwave radiation (Faxa_* basically holds albedo) ---
+ Faxa_swvdr(n) = Faxa_swdn(n)*Faxa_swvdr(n)
+ Faxa_swndr(n) = Faxa_swdn(n)*Faxa_swndr(n)
+ Faxa_swvdf(n) = Faxa_swdn(n)*Faxa_swvdf(n)
+ Faxa_swndf(n) = Faxa_swdn(n)*Faxa_swndf(n)
+
+ !--- swnet: a diagnostic quantity ---
+ Faxa_swnet(n) = Faxa_swndr(n) + Faxa_swvdr(n) + Faxa_swndf(n) + Faxa_swvdf(n)
+ end do
+
+ !----------------------------------------------------------
+ ! unit conversions (temporal resolution is hourly)
+ !----------------------------------------------------------
+
+ ! convert J/m^2 to W/m^2
+ Faxa_lwdn(:) = Faxa_lwdn(:)/3600.0_r8
+ Faxa_swdn(:) = Faxa_swdn(:)/3600.0_r8
+ Faxa_swvdr(:) = Faxa_swvdr(:)/3600.0_r8
+ Faxa_swndr(:) = Faxa_swndr(:)/3600.0_r8
+ Faxa_swvdf(:) = Faxa_swvdf(:)/3600.0_r8
+ Faxa_swndf(:) = Faxa_swndf(:)/3600.0_r8
+ Faxa_swnet(:) = Faxa_swnet(:)/3600.0_r8
+ Faxa_sen(:) = Faxa_sen(:)/3600.0_r8
+ Faxa_lat(:) = Faxa_lat(:)/3600.0_r8
+
+ ! convert m to kg/m^2/s
+ Faxa_rain(:) = Faxa_rain(:)/3600.0_r8*rhofw
+ Faxa_rainc(:) = Faxa_rainc(:)/3600.0_r8*rhofw
+ Faxa_rainl(:) = Faxa_rainl(:)/3600.0_r8*rhofw
+ Faxa_snowc(:) = Faxa_snowc(:)/3600.0_r8*rhofw
+ Faxa_snowl(:) = Faxa_snowl(:)/3600.0_r8*rhofw
+
+ ! convert N/m^2 s to N/m^2
+ Faxa_taux(:) = Faxa_taux(:)/3600.0_r8
+ Faxa_tauy(:) = Faxa_tauy(:)/3600.0_r8
+
+ end subroutine datm_datamode_era5_advance
+
+ !===============================================================================
+ subroutine datm_datamode_era5_restart_write(case_name, inst_suffix, ymd, tod, &
+ logunit, mpicom, my_task, sdat)
+
+ ! input/output variables
+ character(len=*) , intent(in) :: case_name
+ character(len=*) , intent(in) :: inst_suffix
+ integer , intent(in) :: ymd ! model date
+ integer , intent(in) :: tod ! model sec into model date
+ integer , intent(in) :: logunit
+ integer , intent(in) :: my_task
+ integer , intent(in) :: mpicom
+ type(shr_strdata_type) , intent(inout) :: sdat
+ !-------------------------------------------------------------------------------
+
+ call dshr_restart_write(rpfile, case_name, 'datm', inst_suffix, ymd, tod, &
+ logunit, mpicom, my_task, sdat)
+
+ end subroutine datm_datamode_era5_restart_write
+
+ !===============================================================================
+ subroutine datm_datamode_era5_restart_read(rest_filem, inst_suffix, logunit, my_task, mpicom, sdat)
+
+ ! input/output arguments
+ character(len=*) , intent(inout) :: rest_filem
+ character(len=*) , intent(in) :: inst_suffix
+ integer , intent(in) :: logunit
+ integer , intent(in) :: my_task
+ integer , intent(in) :: mpicom
+ type(shr_strdata_type) , intent(inout) :: sdat
+ !-------------------------------------------------------------------------------
+
+ call dshr_restart_read(rest_filem, rpfile, inst_suffix, nullstr, logunit, my_task, mpicom, sdat)
+
+ end subroutine datm_datamode_era5_restart_read
+
+ real(r8) function datm_eSat(tK,tKbot)
+
+ !----------------------------------------------------------------------------
+ ! use polynomials to calculate saturation vapor pressure and derivative with
+ ! respect to temperature: over water when t > 0 c and over ice when t <= 0 c
+ ! required to convert relative humidity to specific humidity
+ !----------------------------------------------------------------------------
+
+ ! input/output variables
+ real(r8),intent(in) :: tK ! temp used in polynomial calculation
+ real(r8),intent(in) :: tKbot ! bottom atm temp
+
+ ! local variables
+ real(r8) :: t ! tK converted to Celcius
+ real(r8),parameter :: tkFrz = shr_const_tkfrz ! freezing T of fresh water ~ K
+
+ !--- coefficients for esat over water ---
+ real(r8),parameter :: a0=6.107799961_r8
+ real(r8),parameter :: a1=4.436518521e-01_r8
+ real(r8),parameter :: a2=1.428945805e-02_r8
+ real(r8),parameter :: a3=2.650648471e-04_r8
+ real(r8),parameter :: a4=3.031240396e-06_r8
+ real(r8),parameter :: a5=2.034080948e-08_r8
+ real(r8),parameter :: a6=6.136820929e-11_r8
+
+ !--- coefficients for esat over ice ---
+ real(r8),parameter :: b0=6.109177956_r8
+ real(r8),parameter :: b1=5.034698970e-01_r8
+ real(r8),parameter :: b2=1.886013408e-02_r8
+ real(r8),parameter :: b3=4.176223716e-04_r8
+ real(r8),parameter :: b4=5.824720280e-06_r8
+ real(r8),parameter :: b5=4.838803174e-08_r8
+ real(r8),parameter :: b6=1.838826904e-10_r8
+
+ t = min( 50.0_r8, max(-50.0_r8,(tK-tKfrz)) )
+ if ( tKbot < tKfrz) then
+ datm_eSat = 100.0_r8*(b0+t*(b1+t*(b2+t*(b3+t*(b4+t*(b5+t*b6))))))
+ else
+ datm_eSat = 100.0_r8*(a0+t*(a1+t*(a2+t*(a3+t*(a4+t*(a5+t*a6))))))
+ end if
+
+ end function datm_eSat
+
+end module datm_datamode_era5_mod