From 8e28de11ad89b7e55981e05bf90a96dfe2d41a94 Mon Sep 17 00:00:00 2001 From: Sean Patrick Santos Date: Thu, 8 Sep 2022 12:31:37 -0700 Subject: [PATCH] Add `scm_zero_non_iop_tracers` option. For single-column runs, this sets all tracers in the atmospheric constituent list to `qmin` (typically zero) after the initial condition file (`ncdata`) is read in, but before the IOP file values are applied. As a result, non-IOP tracers are initialized to `qmin` rather than taking their values from the initial condition file, while IOP-defined tracers are unaffected. This option defaults to `.false.`, and hence does not change answers for existing cases. However, it may be considered safer in the future to change the default to `.true.` (at least for non-replay runs), to avoid inconsistencies between the initial condition file state and the IOP file state that exacerbate transient spin-up behavior and potentially bias free-running model results. Like most single column model options, this option has no effect in global runs. --- .../eam/bld/namelist_files/namelist_definition.xml | 7 +++++++ components/eam/src/control/runtime_opts.F90 | 10 +++++++--- components/eam/src/control/scamMod.F90 | 13 +++++++++++-- .../eam/src/dynamics/eul/eul_single_column_mod.F90 | 5 +++++ .../eam/src/dynamics/se/se_single_column_mod.F90 | 10 +++++++--- 5 files changed, 37 insertions(+), 8 deletions(-) diff --git a/components/eam/bld/namelist_files/namelist_definition.xml b/components/eam/bld/namelist_files/namelist_definition.xml index 66f0adc5e27e..937952169540 100644 --- a/components/eam/bld/namelist_files/namelist_definition.xml +++ b/components/eam/bld/namelist_files/namelist_definition.xml @@ -4095,6 +4095,13 @@ Default: FALSE group="cam_inparm" valid_values=""> Turn off microphysics computation. Default: FALSE + | + | + +Ignore all tracers from initial conditions file, and default all tracers not +specified in IOP to minimum value (usually zero). +Default: FALSE diff --git a/components/eam/src/control/runtime_opts.F90 b/components/eam/src/control/runtime_opts.F90 index 0004ea82a003..dd93692858e4 100644 --- a/components/eam/src/control/runtime_opts.F90 +++ b/components/eam/src/control/runtime_opts.F90 @@ -174,6 +174,7 @@ module runtime_opts logical :: scm_crm_mode logical :: scm_observed_aero logical :: precip_off +logical :: scm_zero_non_iop_tracers contains @@ -324,7 +325,8 @@ subroutine read_namelist(single_column_in, scmlon_in, scmlat_in, nlfilename_in ) namelist /cam_inparm/ iopfile,scm_iop_srf_prop,scm_relaxation, & scm_relaxation_low, scm_relaxation_high, & scm_diurnal_avg,scm_crm_mode,scm_clubb_iop_name, & - scm_observed_aero, precip_off + scm_observed_aero, precip_off, & + scm_zero_non_iop_tracers !----------------------------------------------------------------------- @@ -369,7 +371,8 @@ subroutine read_namelist(single_column_in, scmlon_in, scmlat_in, nlfilename_in ) scm_crm_mode_out=scm_crm_mode, & scm_observed_aero_out=scm_observed_aero, & precip_off_out=precip_off, & - scm_clubb_iop_name_out=scm_clubb_iop_name) + scm_clubb_iop_name_out=scm_clubb_iop_name, & + scm_zero_non_iop_tracers_out=scm_zero_non_iop_tracers) end if ! Read in the cam_inparm namelist from input filename @@ -446,7 +449,8 @@ subroutine read_namelist(single_column_in, scmlon_in, scmlat_in, nlfilename_in ) scm_crm_mode_in=scm_crm_mode, & scm_observed_aero_in=scm_observed_aero, & precip_off_in=precip_off, & - scm_clubb_iop_name_in=scm_clubb_iop_name) + scm_clubb_iop_name_in=scm_clubb_iop_name, & + scm_zero_non_iop_tracers_in=scm_zero_non_iop_tracers) end if endif diff --git a/components/eam/src/control/scamMod.F90 b/components/eam/src/control/scamMod.F90 index 1c2c35004e9c..3ffb2ecb6015 100644 --- a/components/eam/src/control/scamMod.F90 +++ b/components/eam/src/control/scamMod.F90 @@ -184,6 +184,7 @@ module scamMod logical*4, public :: scm_relaxation! use relaxation logical*4, public :: scm_observed_aero ! use observed aerosols in SCM file logical*4, public :: precip_off ! turn off precipitation processes + logical*4, public :: scm_zero_non_iop_tracers ! initialize non-IOP-specified tracers to zero logical*4, public :: use_replay ! use e3sm generated forcing logical*4, public :: use_3dfrc ! use 3d forcing logical*4, public :: have_heat_glob ! dataset contains global energy fixer @@ -203,7 +204,7 @@ subroutine scam_default_opts( scmlat_out,scmlon_out,iopfile_out, & single_column_out,scm_iop_srf_prop_out, scm_relaxation_out, & scm_relaxation_low_out, scm_relaxation_high_out, & scm_diurnal_avg_out, scm_crm_mode_out, scm_observed_aero_out, & - precip_off_out, scm_clubb_iop_name_out) + precip_off_out, scm_clubb_iop_name_out, scm_zero_non_iop_tracers_out) !----------------------------------------------------------------------- real(r8), intent(out), optional :: scmlat_out,scmlon_out character*(max_path_len), intent(out), optional :: iopfile_out @@ -217,6 +218,7 @@ subroutine scam_default_opts( scmlat_out,scmlon_out,iopfile_out, & real(r8), intent(out), optional :: scm_relaxation_low_out real(r8), intent(out), optional :: scm_relaxation_high_out character(len=*), intent(out), optional :: scm_clubb_iop_name_out + logical, intent(out), optional :: scm_zero_non_iop_tracers_out if ( present(scmlat_out) ) scmlat_out = -999._r8 if ( present(scmlon_out) ) scmlon_out = -999._r8 @@ -231,6 +233,7 @@ subroutine scam_default_opts( scmlat_out,scmlon_out,iopfile_out, & if ( present(scm_observed_aero_out)) scm_observed_aero_out = .false. if ( present(precip_off_out)) precip_off_out = .false. if ( present(scm_clubb_iop_name_out) ) scm_clubb_iop_name_out = ' ' + if ( present(scm_zero_non_iop_tracers_out) ) scm_zero_non_iop_tracers_out = .false. end subroutine scam_default_opts @@ -238,7 +241,8 @@ subroutine scam_setopts( scmlat_in, scmlon_in,iopfile_in,single_column_in, & scm_iop_srf_prop_in, scm_relaxation_in, & scm_relaxation_low_in, scm_relaxation_high_in, & scm_diurnal_avg_in, scm_crm_mode_in, scm_observed_aero_in, & - precip_off_in, scm_clubb_iop_name_in) + precip_off_in, scm_clubb_iop_name_in, & + scm_zero_non_iop_tracers_in) !----------------------------------------------------------------------- real(r8), intent(in), optional :: scmlon_in, scmlat_in character*(max_path_len), intent(in), optional :: iopfile_in @@ -252,6 +256,7 @@ subroutine scam_setopts( scmlat_in, scmlon_in,iopfile_in,single_column_in, & character(len=*), intent(in), optional :: scm_clubb_iop_name_in real(r8), intent(in), optional :: scm_relaxation_low_in real(r8), intent(in), optional :: scm_relaxation_high_in + logical, intent(in), optional :: scm_zero_non_iop_tracers_in integer ncid,latdimid,londimid,latsiz,lonsiz,latid,lonid,ret,i integer latidx,lonidx real(r8) ioplat,ioplon @@ -296,6 +301,10 @@ subroutine scam_setopts( scmlat_in, scmlon_in,iopfile_in,single_column_in, & scm_clubb_iop_name=scm_clubb_iop_name_in endif + if (present (scm_zero_non_iop_tracers_in)) then + scm_zero_non_iop_tracers=scm_zero_non_iop_tracers_in + endif + if (present (iopfile_in)) then iopfile=trim(iopfile_in) endif diff --git a/components/eam/src/dynamics/eul/eul_single_column_mod.F90 b/components/eam/src/dynamics/eul/eul_single_column_mod.F90 index b114747eb06e..ac6ee04f5f5a 100644 --- a/components/eam/src/dynamics/eul/eul_single_column_mod.F90 +++ b/components/eam/src/dynamics/eul/eul_single_column_mod.F90 @@ -20,6 +20,8 @@ module eul_single_column_mod subroutine scm_setinitial + use constituents, only: pcnst, qmin + implicit none integer i, j, k, thelev @@ -51,6 +53,9 @@ subroutine scm_setinitial endif if (get_nstep() .eq. 0) then + do i = 1, pcnst + if (scm_zero_non_iop_tracers) q3(1,:,i,1,n3) = qmin(i) + end do do k=thelev,PLEV if (have_t) t3(1,k,1,n3)=tobs(k) if (have_q) q3(1,k,1,1,n3)=qobs(k) diff --git a/components/eam/src/dynamics/se/se_single_column_mod.F90 b/components/eam/src/dynamics/se/se_single_column_mod.F90 index cd9101e5a498..04eaf9618792 100644 --- a/components/eam/src/dynamics/se/se_single_column_mod.F90 +++ b/components/eam/src/dynamics/se/se_single_column_mod.F90 @@ -5,7 +5,7 @@ module se_single_column_mod use element_mod, only: element_t use scamMod -use constituents, only: cnst_get_ind +use constituents, only: cnst_get_ind, pcnst use dimensions_mod, only: nelemd, np use time_manager, only: get_nstep, dtime, is_first_step use ppgrid, only: begchunk @@ -27,11 +27,13 @@ module se_single_column_mod subroutine scm_setinitial(elem) + use constituents, only: qmin + implicit none type(element_t), intent(inout) :: elem(:) - integer i, j, k, ie, thelev + integer i, j, k, cix, ie, thelev integer inumliq, inumice, icldliq, icldice if (.not. use_replay .and. get_nstep() .eq. 0) then @@ -74,6 +76,9 @@ subroutine scm_setinitial(elem) endif if (get_nstep() .eq. 0) then + do cix = 1, pcnst + if (scm_zero_non_iop_tracers) elem(ie)%state%Q(i,j,:,cix) = qmin(cix) + end do do k=thelev, PLEV #ifdef MODEL_THETA_L if (have_t) elem(ie)%derived%FT(i,j,k)=tobs(k) @@ -132,7 +137,6 @@ subroutine apply_SC_forcing(elem,hvcoord,tl,n,t_before_advance,nets,nete) use element_mod, only : element_t use physical_constants, only : Cp, Rgas, cpwater_vapor use time_mod - use constituents, only: pcnst use time_manager, only: get_nstep use shr_const_mod, only: SHR_CONST_PI