diff --git a/Externals.cfg b/Externals.cfg
index c09bd4041e..185f412cab 100644
--- a/Externals.cfg
+++ b/Externals.cfg
@@ -8,7 +8,7 @@ required = True
local_path = components/cism
protocol = git
repo_url = https://github.com/ESCOMP/CISM-wrapper
-tag = cismwrap_2_1_97
+tag = cismwrap_2_1_99
externals = Externals_CISM.cfg
required = True
diff --git a/bld/CLMBuildNamelist.pm b/bld/CLMBuildNamelist.pm
index b4eefd984c..fd8def8845 100755
--- a/bld/CLMBuildNamelist.pm
+++ b/bld/CLMBuildNamelist.pm
@@ -651,9 +651,9 @@ sub process_namelist_commandline_options {
setup_cmdl_dynamic_vegetation($opts, $nl_flags, $definition, $defaults, $nl);
setup_cmdl_fates_mode($opts, $nl_flags, $definition, $defaults, $nl);
setup_cmdl_vichydro($opts, $nl_flags, $definition, $defaults, $nl);
+ setup_logic_lnd_tuning($opts, $nl_flags, $definition, $defaults, $nl, $physv);
setup_cmdl_run_type($opts, $nl_flags, $definition, $defaults, $nl);
setup_cmdl_output_reals($opts, $nl_flags, $definition, $defaults, $nl);
- setup_logic_lnd_tuning($opts, $nl_flags, $definition, $defaults, $nl, $physv);
}
#-------------------------------------------------------------------------------
@@ -1265,6 +1265,8 @@ sub setup_cmdl_simulation_year {
sub setup_cmdl_run_type {
my ($opts, $nl_flags, $definition, $defaults, $nl) = @_;
+ # Set the clm_start_type and the st_year, start year
+ # This MUST be done after lnd_tuning_mode is set
my $val;
my $var = "clm_start_type";
@@ -1279,20 +1281,19 @@ sub setup_cmdl_run_type {
my $group = $definition->get_group_name($date);
$nl->set_variable_value($group, $date, $ic_date );
}
+ my $set = undef;
if (defined $opts->{$var}) {
- if ($opts->{$var} eq "default" ) {
- add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var,
- 'use_cndv'=>$nl_flags->{'use_cndv'}, 'use_fates'=>$nl_flags->{'use_fates'},
- 'sim_year'=>$st_year, 'sim_year_range'=>$nl_flags->{'sim_year_range'},
- 'bgc_spinup'=>$nl_flags->{'bgc_spinup'} );
- } else {
+ if ($opts->{$var} ne "default" ) {
+ $set = 1;
my $group = $definition->get_group_name($var);
$nl->set_variable_value($group, $var, quote_string( $opts->{$var} ) );
}
- } else {
- add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var,
- 'use_cndv'=>$nl_flags->{'use_cndv'}, 'use_fates'=>$nl_flags->{'use_fates'},
- 'sim_year'=>$st_year );
+ }
+ if ( ! defined $set ) {
+ add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var,
+ 'use_cndv'=>$nl_flags->{'use_cndv'}, 'use_fates'=>$nl_flags->{'use_fates'},
+ 'sim_year'=>$st_year, 'sim_year_range'=>$nl_flags->{'sim_year_range'},
+ 'bgc_spinup'=>$nl_flags->{'bgc_spinup'}, 'lnd_tuning_mode'=>$nl_flags->{'lnd_tuning_mode'} );
}
$nl_flags->{'clm_start_type'} = $nl->get_value($var);
$nl_flags->{'st_year'} = $st_year;
@@ -1697,6 +1698,11 @@ sub process_namelist_inline_logic {
#################################
setup_logic_fire_emis($opts, $nl_flags, $definition, $defaults, $nl);
+ ######################################
+ # namelist options for dust emissions
+ ######################################
+ setup_logic_dust_emis($opts, $nl_flags, $definition, $defaults, $nl);
+
#################################
# namelist group: megan_emis_nl #
#################################
@@ -3959,6 +3965,56 @@ sub setup_logic_fire_emis {
#-------------------------------------------------------------------------------
+sub setup_logic_dust_emis {
+ # Logic to handle the dust emissions
+ my ($opts, $nl_flags, $definition, $defaults, $nl) = @_;
+
+ # First get the dust emission method
+ my $var = "dust_emis_method";
+ add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var );
+
+ my $dust_emis_method = remove_leading_and_trailing_quotes( $nl->get_value($var) );
+
+ my @zender_files_in_lnd_opts = ( "stream_fldfilename_zendersoilerod", "stream_meshfile_zendersoilerod",
+ "zendersoilerod_mapalgo" );
+ if ( $dust_emis_method eq "Zender_2003" ) {
+ # get the zender_soil_erod_source
+ add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl,
+ "zender_soil_erod_source", 'dust_emis_method'=>$dust_emis_method );
+
+ my $zender_source = remove_leading_and_trailing_quotes( $nl->get_value('zender_soil_erod_source') );
+ if ( $zender_source eq "lnd" ) {
+ foreach my $option ( @zender_files_in_lnd_opts ) {
+ add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $option,
+ 'dust_emis_method'=>$dust_emis_method, 'zender_soil_erod_source'=>$zender_source,
+ 'hgrid'=>$nl_flags->{'res'}, 'lnd_tuning_mod'=>$nl_flags->{'lnd_tuning_mode'} );
+ }
+ } else {
+ foreach my $option ( @zender_files_in_lnd_opts ) {
+ if ( defined($nl->get_value($option)) ) {
+ $log->fatal_error("zender_soil_erod_source is NOT lnd, but the file option $option is being set" .
+ " and should NOT be unless you want it handled here in the LAND model, " .
+ "otherwise the equivalent option is set in CAM" );
+ }
+ }
+ }
+ } else {
+ # Verify that NONE of the Zender options are being set if Zender is NOT being used
+ push @zender_files_in_lnd_opts, "zender_soil_erod_source";
+ foreach my $option ( @zender_files_in_lnd_opts ) {
+ if ( defined($nl->get_value($option)) ) {
+ $log->fatal_error("dust_emis_method is NOT set to Zender_2003, but one of it's options " .
+ "$option is being set, need to change one or the other" );
+ }
+ }
+ if ( $dust_emis_method eq "Leung_2023" ) {
+ $log->warning("dust_emis_method is Leung_2023 and that option has NOT been brought into CTSM yet");
+ }
+ }
+}
+
+#-------------------------------------------------------------------------------
+
sub setup_logic_megan {
my ($opts, $nl_flags, $definition, $defaults, $nl) = @_;
@@ -4644,6 +4700,7 @@ sub write_output_files {
push @groups, "exice_streams";
push @groups, "soilbgc_decomp";
push @groups, "clm_canopy_inparm";
+ push @groups, "zendersoilerod";
if (remove_leading_and_trailing_quotes($nl->get_value('snow_cover_fraction_method')) eq 'SwensonLawrence2012') {
push @groups, "scf_swenson_lawrence_2012_inparm";
}
diff --git a/bld/namelist_files/namelist_defaults_ctsm.xml b/bld/namelist_files/namelist_defaults_ctsm.xml
index 5c86d230fd..a01839836d 100644
--- a/bld/namelist_files/namelist_defaults_ctsm.xml
+++ b/bld/namelist_files/namelist_defaults_ctsm.xml
@@ -279,6 +279,10 @@ attributes from the config_cache.xml file (with keys converted to upper-case).
>30.0d00
20.0d00
+20.0d00
+20.0d00
80.0d00
0.85d00
0.98d00
@@ -290,6 +294,10 @@ attributes from the config_cache.xml file (with keys converted to upper-case).
>0.010d00
0.008d00
+0.008d00
+0.008d00
0.17d-3
1.6d-4
0.33d00
@@ -657,7 +665,7 @@ attributes from the config_cache.xml file (with keys converted to upper-case).
-.true.
+.true.
.true.
-.true.
-.true.
+.true.
+.true.
.true.
.true.
.true.
+
+
+.false.
+.false.
+.false.
+.false.
+.false.
+.false.
.false.
+
hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.false. glc_nec=10 do_transient_pfts=.false.
@@ -761,6 +776,7 @@ attributes from the config_cache.xml file (with keys converted to upper-case).
hgrid=1.9x2.5 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false.
+
hgrid=1.9x2.5 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false.
@@ -2759,6 +2775,60 @@ use_crop=".true.">lnd/clm2/surfdata_map/ctsm5.1.dev052/landuse.timeseries_mpasa1
lnd/clm2/paramdata/finundated_inversiondata_0.9x1_ESMFmesh_cdf5_130621.nc
+
+
+
+
+
+Zender_2003
+atm
+bilinear
+lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc
+lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc
+lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc
+lnd/clm2/dustemisdata/dst_source2x2_cam5.4-forCLM_cdf5_c240202.nc
+lnd/clm2/dustemisdata/dst_source2x2_cam5.4-forCLM_cdf5_c240202.nc
+lnd/clm2/dustemisdata/dst_source2x2_cam5.4-forCLM_cdf5_c240202.nc
+lnd/clm2/dustemisdata/dst_source2x2tuned-cam4-forCLM_cdf5_c240202.nc
+lnd/clm2/dustemisdata/dst_source2x2tuned-cam4-forCLM_cdf5_c240202.nc
+lnd/clm2/dustemisdata/dst_source2x2tuned-cam4-forCLM_cdf5_c240202.nc
+lnd/clm2/dustemisdata/dst_source1x1tuned-cam4-forCLM_cdf5_c240202.nc
+lnd/clm2/dustemisdata/dst_source1x1tuned-cam4-forCLM_cdf5_c240202.nc
+lnd/clm2/dustemisdata/dst_source1x1tuned-cam4-forCLM_cdf5_c240202.nc
+lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc
+lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc
+lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc
+lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc
+lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc
+lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc
+lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc
+lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc
+lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc
+
+lnd/clm2/dustemisdata/dust_2x2_ESMFmesh_cdf5_c230730.nc
+
diff --git a/bld/namelist_files/namelist_defaults_overall.xml b/bld/namelist_files/namelist_defaults_overall.xml
index 96db00478a..df9981efdf 100644
--- a/bld/namelist_files/namelist_defaults_overall.xml
+++ b/bld/namelist_files/namelist_defaults_overall.xml
@@ -22,6 +22,12 @@ determine default values for namelists.
-->
+cold
+cold
+cold
+cold
+cold
+cold
arb_ic
arb_ic
arb_ic
diff --git a/bld/namelist_files/namelist_definition_ctsm.xml b/bld/namelist_files/namelist_definition_ctsm.xml
index 8b292294c9..a2e9fb86da 100644
--- a/bld/namelist_files/namelist_definition_ctsm.xml
+++ b/bld/namelist_files/namelist_definition_ctsm.xml
@@ -1832,6 +1832,49 @@ Mapping method from Nitrogen deposition input file to the model resolution
copy = copy using the same indices
+
+
+
+
+
+Which dust emission method is going to be used. Either the Zender 2003 scheme or the Leung 2023
+scheme.
+(NOTE: The Leung 2023 method is NOT currently available)
+
+
+
+Option only applying for the Zender_2003 method for whether the soil erodibility file is handled
+here in CTSM, or in the ATM model.
+(only used when dust_emis_method is Zender_2003)
+
+
+
+Option only applying for the Zender_2003 method for whether the soil erodibility file is handled
+here in CTSM, or in the ATM model.
+(only used when dust_emis_method is Zender_2003)
+ bilinear = bilinear interpolation
+ nn = nearest neighbor
+ nnoni = nearest neighbor on the "i" (longitude) axis
+ nnonj = nearest neighbor on the "j" (latitude) axis
+ spval = set to special value
+ copy = copy using the same indices
+
+
+
+Filename of input stream data for Zender's soil erodibility source function
+(only used when dust_emis_method is Zender_2003, and zender_soil_erod_source is lnd)
+
+
+
+mesh filename of input stream data for Zender's soil erodibility source function
+(only used when dust_emis_method is Zender_2003, and zender_soil_erod_source is lnd)
+
+
@@ -2227,7 +2270,7 @@ Land mask description
+ valid_values="clm4_5_CRUv7,clm4_5_GSWP3v1,clm4_5_cam6.0,clm4_5_cam5.0,clm4_5_cam4.0,clm5_0_cam6.0,clm5_0_cam5.0,clm5_0_cam4.0,clm5_0_CRUv7,clm5_0_GSWP3v1,clm5_1_GSWP3v1,clm5_1_CRUv7,clm5_1_cam6.0,clm5_1_cam5.0,clm5_1_cam4.0">
General configuration of model version and atmospheric forcing to tune the model to run under.
This sets the model to run with constants and initial conditions that were set to run well under
the configuration of model version and atmospheric forcing. To run well constants would need to be changed
diff --git a/bld/unit_testers/build-namelist_test.pl b/bld/unit_testers/build-namelist_test.pl
index 6224acc815..f207053924 100755
--- a/bld/unit_testers/build-namelist_test.pl
+++ b/bld/unit_testers/build-namelist_test.pl
@@ -163,10 +163,10 @@ sub cat_and_create_namelistinfile {
#
# Figure out number of tests that will run
#
-my $ntests = 1549;
+my $ntests = 1611;
if ( defined($opts{'compare'}) ) {
- $ntests += 907;
+ $ntests += 945;
}
plan( tests=>$ntests );
@@ -464,6 +464,7 @@ sub cat_and_create_namelistinfile {
"-bgc fates -use_case 1850_control -no-megan -namelist \"&a use_fates_sp=T, soil_decomp_method='None'/\"",
"-bgc sp -use_case 2000_control -res 0.9x1.25 -namelist '&a use_soil_moisture_streams = T/'",
"-bgc bgc -use_case 1850-2100_SSP5-8.5_transient -namelist '&a start_ymd=19101023/'",
+ "-namelist \"&a dust_emis_method='Zender_2003', zender_soil_erod_source='lnd' /'\"",
"-bgc bgc -use_case 2000_control -namelist \"&a fire_method='nofire'/\" -crop",
"-res 0.9x1.25 -bgc sp -use_case 1850_noanthro_control -drydep -fire_emis",
"-res 0.9x1.25 -bgc bgc -use_case 1850_noanthro_control -drydep -fire_emis -light_res 360x720",
@@ -1200,7 +1201,7 @@ sub cat_and_create_namelistinfile {
phys=>"clm5_0",
},
"NOlunabutsetJmaxb1" =>{ options=>"-envxml_dir . -bgc sp",
- namelst=>"use_luna=.false., jmaxb1=1.0",
+ namelst=>"use_luna=.fwlse., jmaxb1=1.0",
GLC_TWO_WAY_COUPLING=>"FALSE",
phys=>"clm5_0",
},
@@ -1234,6 +1235,18 @@ sub cat_and_create_namelistinfile {
GLC_TWO_WAY_COUPLING=>"FALSE",
phys=>"clm5_0",
},
+ "soil_erod_wo_Zender" =>{ options=>"--envxml_dir . --ignore_warnings",
+ namelst=>"dust_emis_method='Leung_2023', " .
+ "stream_meshfile_zendersoilerod = '/dev/null'",
+ GLC_TWO_WAY_COUPLING=>"FALSE",
+ phys=>"clm5_1",
+ },
+ "soil_erod_wo_lnd_source" =>{ options=>"--envxml_dir .",
+ namelst=>"dust_emis_method='Zender_2003', " .
+ "stream_fldfilename_zendersoilerod = '/dev/null', zender_soil_erod_source='atm'",
+ GLC_TWO_WAY_COUPLING=>"FALSE",
+ phys=>"clm5_1",
+ },
);
foreach my $key ( keys(%failtest) ) {
print( "$key\n" );
@@ -1255,6 +1268,11 @@ sub cat_and_create_namelistinfile {
my %warntest = (
# Warnings without the -ignore_warnings option given
+ "dustemisLeung" =>{ options=>"-envxml_dir .",
+ namelst=>"dust_emis_method = 'Leung_2023'",
+ GLC_TWO_WAY_COUPLING=>"FALSE",
+ phys=>"clm5_1",
+ },
"coldwfinidat" =>{ options=>"-envxml_dir . -clm_start_type cold",
namelst=>"finidat = 'testfile.nc'",
GLC_TWO_WAY_COUPLING=>"FALSE",
@@ -1700,9 +1718,9 @@ sub cat_and_create_namelistinfile {
&make_config_cache($phys);
my @forclist = ();
if ( $phys == "clm5_1" ) {
- @forclist = ( "GSWP3v1" );
+ @forclist = ( "GSWP3v1", "cam6.0", "cam5.0", "cam4.0" );
} else {
- @forclist = ( "CRUv7", "GSWP3v1", "cam6.0" );
+ @forclist = ( "CRUv7", "GSWP3v1", "cam6.0", "cam5.0", "cam4.0" );
}
foreach my $forc ( @forclist ) {
foreach my $bgc ( "sp", "bgc" ) {
diff --git a/cime_config/buildnml b/cime_config/buildnml
index 0521830616..f09c45e703 100755
--- a/cime_config/buildnml
+++ b/cime_config/buildnml
@@ -27,6 +27,7 @@ _config_cache_template = """
"""
+
###############################################################################
def buildnml(case, caseroot, compname):
###############################################################################
@@ -59,7 +60,7 @@ def buildnml(case, caseroot, compname):
run_refdate = case.get_value("RUN_REFDATE")
run_reftod = case.get_value("RUN_REFTOD")
glc_nec = case.get_value("GLC_NEC")
- cism_use_antarctica = case.get_value("CISM_USE_ANTARCTICA")
+ glc_use_antarctica = case.get_value("GLC_USE_ANTARCTICA")
mask = case.get_value("MASK_GRID")
driver = case.get_value("COMP_INTERFACE").lower()
@@ -153,19 +154,19 @@ def buildnml(case, caseroot, compname):
else:
nomeg = ""
- if cism_use_antarctica is None:
- # This is the case for compsets without CISM, where the CISM_USE_ANTARCTICA xml
+ if glc_use_antarctica is None:
+ # This is the case for compsets with SGLC where the GLC_USE_ANTARCTICA xml
# variable isn't defined
glc_use_antarctica_flag = ""
- elif isinstance(cism_use_antarctica, bool):
- if cism_use_antarctica:
+ elif isinstance(glc_use_antarctica, bool):
+ if glc_use_antarctica:
glc_use_antarctica_flag = "-glc_use_antarctica"
else:
glc_use_antarctica_flag = ""
else:
expect(
False,
- "Unexpected value for CISM_USE_ANTARCTICA: {}".format(cism_use_antarctica),
+ "Unexpected value for GLC_USE_ANTARCTICA: {}".format(glc_use_antarctica),
)
if clm_nml_use_case != "UNSET":
diff --git a/cime_config/config_component.xml b/cime_config/config_component.xml
index 281a94a0b2..8fecd2f17b 100644
--- a/cime_config/config_component.xml
+++ b/cime_config/config_component.xml
@@ -63,18 +63,28 @@
Tuning parameters and initial conditions should be optimized for what CLM model version and what meteorlogical forcing combination?
UNSET
- clm5_0_cam6.0,clm5_0_GSWP3v1,clm5_0_CRUv7,clm4_5_CRUv7,clm4_5_GSWP3v1,clm4_5_cam6.0,clm5_1_GSWP3v1,clm5_1_cam6.0
+ clm5_0_cam6.0,clm5.0_cam5.0,clm5.0_cam4.0,clm5_0_GSWP3v1,clm5_0_CRUv7,clm4_5_CRUv7,clm4_5_GSWP3v1,clm4_5_cam6.0,clm4_5_cam5.0,clm4_5_cam4.0,clm5_1_GSWP3v1,clm5_1_cam6.0,clm5_1_cam5.0,clm5_1_cam4.0
clm4_5_CRUv7
clm4_5_CRUv7
clm4_5_GSWP3v1
- clm4_5_cam6.0
+ clm4_5_cam4.0
+ clm4_5_cam5.0
+ clm4_5_cam6.0
+ clm4_5_cam6.0
clm4_5_cam6.0
clm5_0_CRUv7
clm5_0_CRUv7
clm5_0_GSWP3v1
- clm5_0_cam6.0
+ clm5_0_cam4.0
+ clm5_0_cam5.0
+ clm5_0_cam6.0
+ clm5_0_cam6.0
clm5_0_cam6.0
+ clm5_1_cam4.0
+ clm5_1_cam5.0
+ clm5_1_cam6.0
+ clm5_1_cam6.0
clm5_1_GSWP3v1
clm5_1_cam6.0
diff --git a/cime_config/testdefs/ExpectedTestFails.xml b/cime_config/testdefs/ExpectedTestFails.xml
index 8a18fc2901..a510f38545 100644
--- a/cime_config/testdefs/ExpectedTestFails.xml
+++ b/cime_config/testdefs/ExpectedTestFails.xml
@@ -113,6 +113,21 @@
#2373
+
+
+
+ FAIL
+ #2453
+
+
+
+
+
+ FAIL
+ #2454
+
+
+
diff --git a/cime_config/testdefs/testlist_clm.xml b/cime_config/testdefs/testlist_clm.xml
index 0e1424fd7c..2b8048a64d 100644
--- a/cime_config/testdefs/testlist_clm.xml
+++ b/cime_config/testdefs/testlist_clm.xml
@@ -52,14 +52,52 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
diff --git a/cime_config/testdefs/testmods_dirs/clm/clm45cam4LndTuningModeZDustSoilErod/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/clm45cam4LndTuningModeZDustSoilErod/include_user_mods
new file mode 100644
index 0000000000..fe0e18cf88
--- /dev/null
+++ b/cime_config/testdefs/testmods_dirs/clm/clm45cam4LndTuningModeZDustSoilErod/include_user_mods
@@ -0,0 +1 @@
+../default
diff --git a/cime_config/testdefs/testmods_dirs/clm/clm45cam4LndTuningModeZDustSoilErod/shell_commands b/cime_config/testdefs/testmods_dirs/clm/clm45cam4LndTuningModeZDustSoilErod/shell_commands
new file mode 100644
index 0000000000..010b5b5680
--- /dev/null
+++ b/cime_config/testdefs/testmods_dirs/clm/clm45cam4LndTuningModeZDustSoilErod/shell_commands
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+./xmlchange LND_TUNING_MODE="clm4_5_cam4.0"
+./xmlchange ROF_NCPL='$ATM_NCPL'
+
diff --git a/cime_config/testdefs/testmods_dirs/clm/clm45cam4LndTuningModeZDustSoilErod/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/clm45cam4LndTuningModeZDustSoilErod/user_nl_clm
new file mode 100644
index 0000000000..93b7ee2e48
--- /dev/null
+++ b/cime_config/testdefs/testmods_dirs/clm/clm45cam4LndTuningModeZDustSoilErod/user_nl_clm
@@ -0,0 +1,3 @@
+! Turn on using the soil eroditability file in CTSM
+dust_emis_method = 'Zender_2003'
+zender_soil_erod_source = 'lnd'
diff --git a/cime_config/testdefs/testmods_dirs/clm/clm50cam5LndTuningModeZDustSoilErod/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/clm50cam5LndTuningModeZDustSoilErod/include_user_mods
new file mode 100644
index 0000000000..fe0e18cf88
--- /dev/null
+++ b/cime_config/testdefs/testmods_dirs/clm/clm50cam5LndTuningModeZDustSoilErod/include_user_mods
@@ -0,0 +1 @@
+../default
diff --git a/cime_config/testdefs/testmods_dirs/clm/clm50cam5LndTuningModeZDustSoilErod/shell_commands b/cime_config/testdefs/testmods_dirs/clm/clm50cam5LndTuningModeZDustSoilErod/shell_commands
new file mode 100644
index 0000000000..753bc2f045
--- /dev/null
+++ b/cime_config/testdefs/testmods_dirs/clm/clm50cam5LndTuningModeZDustSoilErod/shell_commands
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+./xmlchange LND_TUNING_MODE="clm5_0_cam5.0"
+./xmlchange ROF_NCPL='$ATM_NCPL'
+
diff --git a/cime_config/testdefs/testmods_dirs/clm/clm50cam5LndTuningModeZDustSoilErod/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/clm50cam5LndTuningModeZDustSoilErod/user_nl_clm
new file mode 100644
index 0000000000..93b7ee2e48
--- /dev/null
+++ b/cime_config/testdefs/testmods_dirs/clm/clm50cam5LndTuningModeZDustSoilErod/user_nl_clm
@@ -0,0 +1,3 @@
+! Turn on using the soil eroditability file in CTSM
+dust_emis_method = 'Zender_2003'
+zender_soil_erod_source = 'lnd'
diff --git a/cime_config/testdefs/testmods_dirs/clm/clm51cam6LndTuningModeZDustSoilErod/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/clm51cam6LndTuningModeZDustSoilErod/include_user_mods
new file mode 100644
index 0000000000..aa76c52034
--- /dev/null
+++ b/cime_config/testdefs/testmods_dirs/clm/clm51cam6LndTuningModeZDustSoilErod/include_user_mods
@@ -0,0 +1 @@
+../clm51cam6LndTuningMode
diff --git a/cime_config/testdefs/testmods_dirs/clm/clm51cam6LndTuningModeZDustSoilErod/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/clm51cam6LndTuningModeZDustSoilErod/user_nl_clm
new file mode 100644
index 0000000000..93b7ee2e48
--- /dev/null
+++ b/cime_config/testdefs/testmods_dirs/clm/clm51cam6LndTuningModeZDustSoilErod/user_nl_clm
@@ -0,0 +1,3 @@
+! Turn on using the soil eroditability file in CTSM
+dust_emis_method = 'Zender_2003'
+zender_soil_erod_source = 'lnd'
diff --git a/doc/ChangeLog b/doc/ChangeLog
index f822c5a72e..d58d7150dd 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,4 +1,70 @@
===============================================================
+Tag name: ctsm5.1.dev176
+Originator(s): afoster (Adrianna Foster,UCAR/TSS,303-497-1728)
+Date: Thu 04 Apr 2024 06:29:36 PM MDT
+One-line Summary: Merge b4b-dev
+
+Purpose and description of changes
+----------------------------------
+
+change needed for the addition of a dglc component in cdeps #2449
+Move the dust emission source function soil erodibility for the Zender scheme from CAM to CTSM #1967
+
+
+Significant changes to scientifically-supported configurations
+--------------------------------------------------------------
+
+Does this tag change answers significantly for any of the following physics configurations?
+(Details of any changes will be given in the "Answer changes" section below.)
+
+
+[ ] clm5_1
+
+[ ] clm5_0
+
+[ ] ctsm5_0-nwp
+
+[ ] clm4_5
+
+
+Bugs fixed
+----------
+[Remove any lines that don't apply. Remove entire section if nothing applies.]
+
+CTSM issues fixed (include CTSM Issue #):
+Closes #2222 - Fixing Negative Ice Fluxes from Ocean to Glacier
+Closes #2117 - Add LND_TUNING_MODE for CAM4, CAM5, CAM7
+Addresses #2149 - Change handling of LND_TUNING_MODE so user is warned of which option is used, add more supported options
+Addresses part of #1836 - Move the soil erodibility dataset dust emission source function from CAM to CTSM
+Helps with ESCOMP/CAM#651 - Move the dust emission source function and global tuning factor from CAM to CTSM
+
+Known bugs introduced in this tag (include issue #):
+
+Notes of particular relevance for users
+---------------------------------------
+
+Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): new namelist options for dust
+
+
+Testing summary:
+----------------
+
+ build-namelist tests (if CLMBuildNamelist.pm has changed):
+
+ derecho - PASS
+
+ regular tests
+
+ derecho ----- OK
+ izumi ------- OK
+
+Pull Requests that document the changes (include PR ids):
+(https://github.com/ESCOMP/ctsm/pull):
+
+https://github.com/ESCOMP/CTSM/pull/2455
+
+===============================================================
+===============================================================
Tag name: ctsm5.1.dev175
Originator(s): slevis (Samuel Levis,UCAR/TSS,303-665-1310)
Date: Thu 21 Mar 2024 05:49:04 PM MDT
diff --git a/doc/ChangeSum b/doc/ChangeSum
index e8c32d90a8..2464a4980f 100644
--- a/doc/ChangeSum
+++ b/doc/ChangeSum
@@ -1,5 +1,6 @@
Tag Who Date Summary
============================================================================================================================
+ ctsm5.1.dev176 afoster 04/04/2024 Merge b4b-dev
ctsm5.1.dev175 slevis 03/21/2024 merge-b4bdev-20240321
ctsm5.1.dev174 olyson 03/14/2024 Improve vegetation health at high latitudes
ctsm5.1.dev173 rgknox 03/13/2024 New FATES namelist variable: fates_history_dimlevel
diff --git a/src/biogeochem/DUSTMod.F90 b/src/biogeochem/DUSTMod.F90
index a86531ba62..ffa2bfe6f0 100644
--- a/src/biogeochem/DUSTMod.F90
+++ b/src/biogeochem/DUSTMod.F90
@@ -30,6 +30,8 @@ module DUSTMod
use LandunitType , only : lun
use ColumnType , only : col
use PatchType , only : patch
+ use ZenderSoilErodStreamType, only : soil_erod_stream_type
+ use clm_varctl , only : dust_emis_method
!
! !PUBLIC TYPES
implicit none
@@ -59,7 +61,8 @@ module DUSTMod
real(r8), pointer, private :: vlc_trb_2_patch (:) ! turbulent deposition velocity 2(m/s)
real(r8), pointer, private :: vlc_trb_3_patch (:) ! turbulent deposition velocity 3(m/s)
real(r8), pointer, private :: vlc_trb_4_patch (:) ! turbulent deposition velocity 4(m/s)
- real(r8), pointer, private :: mbl_bsn_fct_col (:) ! basin factor
+ type(soil_erod_stream_type), private :: soil_erod_stream ! Zender soil erodibility stream data
+ real(r8), pointer, private :: mbl_bsn_fct_col (:) ! [dimensionless] basin factor, or soil erodibility, time-constant
contains
@@ -78,11 +81,13 @@ module DUSTMod
contains
!------------------------------------------------------------------------
- subroutine Init(this, bounds)
+ subroutine Init(this, bounds, NLFilename)
class(dust_type) :: this
type(bounds_type), intent(in) :: bounds
+ character(len=*), intent(in) :: NLFilename
+ call this%soil_erod_stream%Init( bounds, NLFilename )
call this%InitAllocate (bounds)
call this%InitHistory (bounds)
call this%InitCold (bounds)
@@ -112,7 +117,7 @@ subroutine InitAllocate(this, bounds)
allocate(this%vlc_trb_2_patch (begp:endp)) ; this%vlc_trb_2_patch (:) = nan
allocate(this%vlc_trb_3_patch (begp:endp)) ; this%vlc_trb_3_patch (:) = nan
allocate(this%vlc_trb_4_patch (begp:endp)) ; this%vlc_trb_4_patch (:) = nan
- allocate(this%mbl_bsn_fct_col (begc:endc)) ; this%mbl_bsn_fct_col (:) = nan
+ allocate(this%mbl_bsn_fct_col (begc:endc)) ; this%mbl_bsn_fct_col (:) = nan
end subroutine InitAllocate
@@ -129,9 +134,11 @@ subroutine InitHistory(this, bounds)
!
! !LOCAL VARIABLES:
integer :: begp,endp
+ integer :: begc,endc
!------------------------------------------------------------------------
begp = bounds%begp; endp = bounds%endp
+ begc = bounds%begc; endc = bounds%endc
this%flx_mss_vrt_dst_tot_patch(begp:endp) = spval
call hist_addfld1d (fname='DSTFLXT', units='kg/m2/s', &
@@ -158,6 +165,15 @@ subroutine InitHistory(this, bounds)
avgflag='A', long_name='turbulent deposition velocity 4', &
ptr_patch=this%vlc_trb_4_patch, default='inactive')
+ if (dust_emis_method == 'Zender_2003') then
+ if ( this%soil_erod_stream%UseStreams() )then
+ this%mbl_bsn_fct_col(begc:endc) = spval
+ call hist_addfld1d (fname='LND_MBL', units='fraction', &
+ avgflag='A', long_name='Soil erodibility factor', &
+ ptr_col=this%mbl_bsn_fct_col, default='inactive')
+ end if
+ end if
+
end subroutine InitHistory
!-----------------------------------------------------------------------
@@ -173,13 +189,26 @@ subroutine InitCold(this, bounds)
! Set basin factor to 1 for now
- do c = bounds%begc, bounds%endc
- l = col%landunit(c)
-
- if (.not.lun%lakpoi(l)) then
- this%mbl_bsn_fct_col(c) = 1.0_r8
+ if (dust_emis_method == 'Leung_2023') then
+ !do c = bounds%begc, bounds%endc
+ ! l = col%landunit(c)
+
+ ! if (.not.lun%lakpoi(l)) then
+ ! this%mbl_bsn_fct_col(c) = 1.0_r8
+ ! end if
+ !end do
+ call endrun( msg="Leung_2023 dust_emis_method is currently not available"//errMsg(sourcefile, __LINE__))
+ else if (dust_emis_method == 'Zender_2003') then
+ if ( this%soil_erod_stream%UseStreams() )then
+ call this%soil_erod_stream%CalcDustSource( bounds, &
+ this%mbl_bsn_fct_col(bounds%begc:bounds%endc) )
+ else
+ this%mbl_bsn_fct_col(:) = 1.0_r8
end if
- end do
+ else
+ write(iulog,*) 'dust_emis_method not recognized = ', trim(dust_emis_method)
+ call endrun( msg="dust_emis_method namelist item is not valid "//errMsg(sourcefile, __LINE__))
+ end if
end subroutine InitCold
@@ -262,7 +291,7 @@ subroutine DustEmission (bounds, &
fv => frictionvel_inst%fv_patch , & ! Input: [real(r8) (:) ] friction velocity (m/s) (for dust model)
u10 => frictionvel_inst%u10_patch , & ! Input: [real(r8) (:) ] 10-m wind (m/s) (created for dust model)
- mbl_bsn_fct => dust_inst%mbl_bsn_fct_col , & ! Input: [real(r8) (:) ] basin factor
+ mbl_bsn_fct => dust_inst%mbl_bsn_fct_col , & ! Input: [real(r8) (:) ] basin factor
flx_mss_vrt_dst => dust_inst%flx_mss_vrt_dst_patch , & ! Output: [real(r8) (:,:) ] surface dust emission (kg/m**2/s)
flx_mss_vrt_dst_tot => dust_inst%flx_mss_vrt_dst_tot_patch & ! Output: [real(r8) (:) ] total dust flux back to atmosphere (pft)
)
@@ -681,10 +710,6 @@ subroutine InitDustVars(this, bounds)
real(r8), parameter :: dns_slt = 2650.0_r8 ! [kg m-3] Density of optimal saltation particles
!------------------------------------------------------------------------
- associate(&
- mbl_bsn_fct => this%mbl_bsn_fct_col & ! Output: [real(r8) (:)] basin factor
- )
-
! allocate module variable
allocate (ovr_src_snk_mss(dst_src_nbr,ndst))
allocate (dmt_vwr(ndst))
@@ -920,8 +945,6 @@ subroutine InitDustVars(this, bounds)
stk_crc(m) = vlc_grv(m) / vlc_stk(m)
end do
- end associate
-
end subroutine InitDustVars
end module DUSTMod
diff --git a/src/cpl/share_esmf/ZenderSoilErodStreamType.F90 b/src/cpl/share_esmf/ZenderSoilErodStreamType.F90
new file mode 100644
index 0000000000..194e022132
--- /dev/null
+++ b/src/cpl/share_esmf/ZenderSoilErodStreamType.F90
@@ -0,0 +1,374 @@
+module ZenderSoilErodStreamType
+#include "shr_assert.h"
+
+ !-----------------------------------------------------------------------
+ ! !DESCRIPTION:
+ ! Contains methods for reading in the Zender et al. (2003b) Dust source function streams file that has been read in from CAM instead of CLM. dmleung 11 Mar 2023
+ ! pathname in CAM: /glade/p/cesmdata/cseg/inputdata/atm/cam/dst/
+ ! relevant filenames: (CAM6) dst_source2x2tunedcam6-2x2-04062017.nc (default)
+ ! (CAM5) dst_source2x2_cam5.4_c150327.nc
+ ! (CAM4) dst_source2x2tuned-cam4-06132012.nc
+ ! These files are largely similar and the differences are mainly only a little tuning.
+ ! This .F90 file for now only deals with the CAM6 source function, which can be used in CAM5 and CAM4 too. Not sure if we will expand the code to include a namelist control to deal
+ ! with the other files.
+ !
+ ! !USES
+ use ESMF , only : ESMF_LogFoundError, ESMF_LOGERR_PASSTHRU, ESMF_Finalize, ESMF_END_ABORT
+ use dshr_strdata_mod , only : shr_strdata_type
+ use shr_kind_mod , only : r8 => shr_kind_r8, CL => shr_kind_cl
+ use shr_log_mod , only : errMsg => shr_log_errMsg
+ use spmdMod , only : mpicom, masterproc
+ use clm_varctl , only : iulog
+ use abortutils , only : endrun
+ use decompMod , only : bounds_type
+
+ ! !PUBLIC TYPES:
+ implicit none
+ private
+
+ type, public :: soil_erod_stream_type
+ real(r8), pointer, private :: soil_erodibility (:) ! Zender et al. (2003b) dust source function (or soil erodibility)
+ contains
+
+ ! !PUBLIC MEMBER FUNCTIONS:
+ procedure, public :: Init ! Initialize and read data in
+ procedure, public :: CalcDustSource ! Calculate dust source spatial filter (basically truncating stream data value smaller than 0.1 following CAM's practice) based on input streams
+ procedure, public :: UseStreams ! If streams will be used
+
+ ! !PRIVATE MEMBER FUNCTIONS:
+ procedure, private :: InitAllocate ! Allocate data
+
+ end type soil_erod_stream_type
+
+ ! ! PRIVATE DATA:
+ type, private :: streamcontrol_type
+ character(len=CL) :: zender_soil_erod_source ! if calculed in lnd or atm
+ character(len=CL) :: stream_fldFileName_zendersoilerod ! data Filename
+ character(len=CL) :: stream_meshfile_zendersoilerod ! mesh Filename
+ character(len=CL) :: zendersoilerod_mapalgo ! map algo
+ logical :: namelist_set = .false. ! if namelist was set yet
+ contains
+ procedure, private :: ReadNML ! Read in namelist
+ end type streamcontrol_type
+
+ type(streamcontrol_type), private :: control ! Stream control data
+
+ character(len=*), parameter, private :: sourcefile = &
+ __FILE__
+
+!==============================================================================
+contains
+!==============================================================================
+
+ subroutine Init(this, bounds, NLFilename)
+ !
+ ! Initialize the Zender soil eroditability stream object
+ !
+ ! Uses:
+ use spmdMod , only : iam
+ use lnd_comp_shr , only : mesh, model_clock
+ use dshr_strdata_mod , only : shr_strdata_init_from_inline, shr_strdata_print
+ use dshr_strdata_mod , only : shr_strdata_advance
+ use dshr_methods_mod , only : dshr_fldbun_getfldptr
+ !
+ ! arguments
+ implicit none
+ class(soil_erod_stream_type) :: this
+ type(bounds_type), intent(in) :: bounds
+ character(len=*), intent(in) :: NLFilename ! Namelist filename
+ !
+ ! local variables
+ integer :: ig, g, n ! Indices
+ integer :: year ! year (0, ...) for nstep+1
+ integer :: mon ! month (1, ..., 12) for nstep+1
+ integer :: day ! day of month (1, ..., 31) for nstep+1
+ integer :: sec ! seconds into current date for nstep+1
+ integer :: mcdate ! Current model date (yyyymmdd)
+ type(shr_strdata_type) :: sdat_erod ! input data stream
+ character(len=16), allocatable :: stream_varnames(:) ! array of stream field names
+ integer :: rc ! error code
+ real(r8), pointer :: dataptr1d(:) ! temporary pointer
+ character(len=*), parameter :: stream_name = 'zendersoilerod'
+ !-----------------------------------------------------------------------
+
+ call control%ReadNML( bounds, NLFileName )
+ call this%InitAllocate( bounds )
+
+ if ( this%useStreams() )then ! is this a namelist input and is it set in namelist default
+
+ allocate(stream_varnames(1))
+ stream_varnames = (/"mbl_bsn_fct_geo"/) ! varname in the dust source file; the variable is dimensionless
+
+ if (masterproc) then
+ write(iulog,*) ' stream_varnames = ',stream_varnames
+ flush(iulog)
+ end if
+
+ ! Initialize the cdeps data type sdat_erod
+ call shr_strdata_init_from_inline(sdat_erod, & ! what is this function and where does it come from?
+ my_task = iam, &
+ logunit = iulog, &
+ compname = 'LND', &
+ model_clock = model_clock, &
+ model_mesh = mesh, &
+ stream_meshfile = control%stream_meshfile_zendersoilerod, &
+ stream_lev_dimname = 'null', &
+ stream_mapalgo = control%zendersoilerod_mapalgo, &
+ stream_filenames = (/trim(control%stream_fldFileName_zendersoilerod)/), &
+ stream_fldlistFile = stream_varnames, &
+ stream_fldListModel = stream_varnames, &
+ stream_yearFirst = 2003, &
+ stream_yearLast = 2003, &
+ stream_yearAlign = 1, &
+ stream_offset = 0, &
+ stream_taxmode = 'extend', &
+ stream_dtlimit = 1.0e30_r8, &
+ stream_tintalgo = 'linear', &
+ stream_name = 'Zender soil erodibility', &
+ rc = rc)
+ if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then
+ write(iulog,*) 'Error on stream initialize -- see PET*.ESMF_LogFile(s)'
+ call endrun("ESMF log error")
+ end if
+
+ ! Explicitly set current date to a hardcoded constant value. Otherwise
+ ! using the real date can cause roundoff differences that are
+ ! detrected as issues with exact restart. EBK M05/20/2017
+ ! call get_curr_date(year, mon, day, sec)
+ year = 2003
+ mon = 12
+ day = 31
+ sec = 0
+ mcdate = year*10000 + mon*100 + day
+
+ call shr_strdata_advance(sdat_erod, ymd=mcdate, tod=sec, logunit=iulog, istr='zendersoilerod', rc=rc) ! what is istr and do I need to change elsewhere because the change of istr here
+ if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then
+ write(iulog,*) 'Error on stream advance -- see PET*.ESMF_LogFile(s)'
+ call endrun("ESMF log error")
+ end if
+
+ ! Get pointer for stream data that is time and spatially interpolate to model time and grid
+ do n = 1,size(stream_varnames)
+ call dshr_fldbun_getFldPtr(sdat_erod%pstrm(1)%fldbun_model, stream_varnames(n), fldptr1=dataptr1d, rc=rc)
+ if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then
+ write(iulog,*) 'Error on get field pointer -- see PET*.ESMF_LogFile(s)'
+ call endrun("ESMF log error")
+ end if
+ if (trim(stream_varnames(n)) == 'mbl_bsn_fct_geo') then
+ ig = 0
+ do g = bounds%begg,bounds%endg
+ ig = ig+1
+ this%soil_erodibility(g) = dataptr1d(ig)
+ end do
+
+ end if
+
+ end do
+ ! TODO: EBK 03/25/2024: When shr_strdata adds a clean method we should invoke it here to save memory
+ ! This is talked about in https://github.com/ESCOMP/CDEPS/issues/261
+
+ end if
+
+ end subroutine Init
+
+ !==============================================================================
+ logical function UseStreams(this)
+ !
+ ! !DESCRIPTION:
+ ! Return true if the Zender method is being used and the soil erodability
+ ! file is being used with it
+ !
+ ! !USES:
+ use clm_varctl, only : dust_emis_method
+ !
+ ! !ARGUMENTS:
+ implicit none
+ class(soil_erod_stream_type) :: this
+ !
+ ! !LOCAL VARIABLES:
+ if ( .not. control%namelist_set )then
+ call endrun(msg=' ERROR namelist NOT set before being used'//errMsg(sourcefile, __LINE__))
+ end if
+ if ( (trim(dust_emis_method) == 'Zender_2003') .and. (control%zender_soil_erod_source == "lnd") )then
+ UseStreams = .true.
+ else
+ UseStreams = .false.
+ end if
+ end function UseStreams
+
+ !==============================================================================
+ subroutine InitAllocate(this, bounds)
+ !
+ ! !DESCRIPTION:
+ ! Allocate module variables and data structures
+ !
+ ! !USES:
+ use shr_infnan_mod, only: nan => shr_infnan_nan, assignment(=)
+ !
+ ! !ARGUMENTS:
+ implicit none
+ class(soil_erod_stream_type) :: this
+ type(bounds_type), intent(in) :: bounds
+ !
+ ! !LOCAL VARIABLES:
+ integer :: begg, endg
+ !---------------------------------------------------------------------
+
+ begg = bounds%begg; endg = bounds%endg
+
+ if ( this%useStreams() ) then
+ allocate(this%soil_erodibility (begg:endg))
+ else
+ allocate(this%soil_erodibility (0))
+ end if
+ this%soil_erodibility (:) = nan
+
+ end subroutine InitAllocate
+
+ !==============================================================================
+ subroutine CalcDustSource(this, bounds, soil_erod)
+ !
+ ! !DESCRIPTION:
+ ! Calculate the soil eroditability for the Zender dust method.
+ !
+ ! !USES:
+ use ColumnType , only : col
+ !use PatchType , only : patch
+ !USES
+ use landunit_varcon , only : istdlak
+ use LandunitType , only : lun
+ !
+ ! !ARGUMENTS:
+ implicit none
+ class(soil_erod_stream_type) :: this
+ type(bounds_type) , intent(in) :: bounds
+ real(r8) , intent(inout) :: soil_erod(bounds%begc:) ! [fraction] rock drag partition factor (roughness effect)
+ !
+ ! !LOCAL VARIABLES:
+ !integer :: g, c, fc ! Indices
+ integer :: g, p, fp, l, c ! Indices
+ !real(r8) :: z0s ! smooth roughness length (m)
+
+ ! constants
+ real(r8),parameter :: soil_erod_threshold = 0.1_r8 ! CAM soil erodibility threshold; below threshold -> soil_erod = 0_r8 11 Mar 2023
+ !---------------------------------------------------------------------
+
+ SHR_ASSERT_ALL_FL((ubound(soil_erod) == (/bounds%endc/)), sourcefile, __LINE__)
+
+ !associate( &
+ !z => col%z & ! Input: [real(r8) (:,:) ] layer depth (m) (-nlevsno+1:nlevsoi)
+ !)
+
+
+ ! dmleung: this loop truncates soil erodibility values smaller than a threshold value (set as 0.1). We save the drag partition factor as a grid level quantity.
+ do c = bounds%begc,bounds%endc
+ g = col%gridcell(c)
+ l = col%landunit(c)
+ if (lun%itype(l) /= istdlak) then ! not lake (can only be used during initialization)
+
+ if (this%soil_erodibility(g) .lt. soil_erod_threshold ) then
+ soil_erod(c) = 0._r8
+ else
+ soil_erod(c) = this%soil_erodibility(g)
+ end if
+
+ end if
+ end do
+
+ !end associate
+
+ end subroutine CalcDustSource
+
+ !==============================================================================
+ subroutine ReadNML(this, bounds, NLFilename)
+ !
+ ! Read the namelist data stream information for the Zender method soil
+ ! eroditability file
+ !
+ ! Uses:
+ use shr_nl_mod , only : shr_nl_find_group_name
+ use shr_log_mod , only : errMsg => shr_log_errMsg
+ use shr_mpi_mod , only : shr_mpi_bcast
+ !
+ ! arguments
+ implicit none
+ class(streamcontrol_type) :: this
+ type(bounds_type), intent(in) :: bounds
+ character(len=*), intent(in) :: NLFilename ! Namelist filename
+ !
+ ! local variables
+ integer :: i ! Indices
+ integer :: nu_nml ! unit for namelist file
+ integer :: nml_error ! namelist i/o error flag
+ character(len=CL) :: stream_fldFileName_zendersoilerod = ' '
+ character(len=CL) :: stream_meshfile_zendersoilerod = ' '
+ character(len=CL) :: zendersoilerod_mapalgo = ' '
+ character(len=CL) :: tmp_file_array(3)
+ character(len=3) :: zender_soil_erod_source = 'atm'
+ character(len=*), parameter :: namelist_name = 'zendersoilerod' ! MUST agree with group name in namelist definition to read.
+ character(len=*), parameter :: subName = "('zendersoilerod::ReadNML')"
+ !-----------------------------------------------------------------------
+
+ namelist /zendersoilerod/ & ! MUST agree with namelist_name above
+ zendersoilerod_mapalgo, stream_fldFileName_zendersoilerod, &
+ stream_meshfile_zendersoilerod, zender_soil_erod_source
+
+ ! Default values for namelist
+
+ ! Read zenderdustsource namelist
+ if (masterproc) then
+ open( newunit=nu_nml, file=trim(NLFilename), status='old', iostat=nml_error )
+ call shr_nl_find_group_name(nu_nml, namelist_name, status=nml_error)
+ if (nml_error == 0) then
+ read(nu_nml, nml=zendersoilerod, iostat=nml_error) ! MUST agree with namelist_name above
+ if (nml_error /= 0) then
+ call endrun(msg=' ERROR reading '//namelist_name//' namelist'//errMsg(sourcefile, __LINE__))
+ end if
+ else
+ call endrun(msg=' ERROR finding '//namelist_name//' namelist'//errMsg(sourcefile, __LINE__))
+ end if
+ close(nu_nml)
+ endif
+
+ call shr_mpi_bcast(zender_soil_erod_source , mpicom)
+ call shr_mpi_bcast(zendersoilerod_mapalgo , mpicom)
+ call shr_mpi_bcast(stream_fldFileName_zendersoilerod , mpicom)
+ call shr_mpi_bcast(stream_meshfile_zendersoilerod , mpicom)
+
+ if (masterproc .and. (zender_soil_erod_source == "lnd") ) then
+ write(iulog,*) ' '
+ write(iulog,*) namelist_name, ' stream settings:'
+ write(iulog,*) ' stream_fldFileName_zendersoilerod = ',stream_fldFileName_zendersoilerod
+ write(iulog,*) ' stream_meshfile_zendersoilerod = ',stream_meshfile_zendersoilerod
+ write(iulog,*) ' zendersoilerod_mapalgo = ',zendersoilerod_mapalgo
+ endif
+
+ if ( (trim(zender_soil_erod_source) /= 'atm') .and. (trim(zender_soil_erod_source) /= 'lnd') )then
+ call endrun(msg=' ERROR zender_soil_erod_source must be either lnd or atm and is NOT'//errMsg(sourcefile, __LINE__))
+ end if
+ tmp_file_array(1) = stream_fldFileName_zendersoilerod
+ tmp_file_array(2) = stream_meshfile_zendersoilerod
+ tmp_file_array(3) = zendersoilerod_mapalgo
+ if ( trim(zender_soil_erod_source) == 'lnd' )then
+ do i = 1, size(tmp_file_array)
+ if ( len_trim(tmp_file_array(i)) == 0 )then
+ call endrun(msg=' ERROR '//trim(tmp_file_array(i))//' must be set when Zender_2003 is being used and zender_soil_erod_source is lnd'//errMsg(sourcefile, __LINE__))
+ end if
+ end do
+ else
+ do i = 1, size(tmp_file_array)
+ if ( len_trim(tmp_file_array(i)) > 0 )then
+ call endrun(msg=' ERROR '//trim(tmp_file_array(i))//' is set and MUST iNOT be when Zender_2003 is NOT being used or zender_soil_erod_source is atm'//errMsg(sourcefile, __LINE__))
+ end if
+ end do
+ end if
+ this%stream_fldFileName_zendersoilerod = stream_fldFileName_zendersoilerod
+ this%stream_meshfile_zendersoilerod = stream_meshfile_zendersoilerod
+ this%zendersoilerod_mapalgo = zendersoilerod_mapalgo
+ this%zender_soil_erod_source = zender_soil_erod_source
+
+ this%namelist_set = .true.
+
+ end subroutine ReadNML
+
+end module ZenderSoilErodStreamType
diff --git a/src/main/clm_instMod.F90 b/src/main/clm_instMod.F90
index 43390ca8b7..b9d74c418a 100644
--- a/src/main/clm_instMod.F90
+++ b/src/main/clm_instMod.F90
@@ -350,7 +350,7 @@ subroutine clm_instInit(bounds)
call surfrad_inst%Init(bounds)
- call dust_inst%Init(bounds)
+ call dust_inst%Init(bounds, NLFilename)
allocate(scf_method, source = CreateAndInitSnowCoverFraction( &
snow_cover_fraction_method = snow_cover_fraction_method, &
diff --git a/src/main/clm_varctl.F90 b/src/main/clm_varctl.F90
index 267c425d7d..389ed50f88 100644
--- a/src/main/clm_varctl.F90
+++ b/src/main/clm_varctl.F90
@@ -271,6 +271,11 @@ module clm_varctl
! option to activate OC in snow in SNICAR
logical, public :: do_sno_oc = .false. ! control to include organic carbon (OC) in snow
+ !----------------------------------------------------------
+ ! DUST emission method
+ !----------------------------------------------------------
+ character(len=25), public :: dust_emis_method = 'Zender_2003' ! Dust emisison method to use: Zender_2003 or Leung_2023
+
!----------------------------------------------------------
! C isotopes
!----------------------------------------------------------
diff --git a/src/main/controlMod.F90 b/src/main/controlMod.F90
index a5da9c3082..dc9622ddac 100644
--- a/src/main/controlMod.F90
+++ b/src/main/controlMod.F90
@@ -207,6 +207,12 @@ subroutine control_init(dtime)
for_testing_no_crop_seed_replenishment, &
z0param_method, use_z0m_snowmelt
+ ! NOTE: EBK 02/26/2024: dust_emis_method is here in CTSM temporarily until it's moved to CMEPS
+ ! See: https://github.com/ESCOMP/CMEPS/pull/429
+ ! Normally this should also need error checking and a broadcast, but since
+ ! there is only one hardcoded option right now that is unneeded.
+ namelist /clm_inparm/ dust_emis_method
+
! vertical soil mixing variables
namelist /clm_inparm/ &
som_adv_flux, max_depth_cryoturb