diff --git a/.gitmodules b/.gitmodules
index 48bc074b92..0d39ebff4e 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -58,8 +58,8 @@ fxrequired = ToplevelRequired
fxDONOTUSEurl = https://github.com/ESCOMP/MOSART
[submodule "mizuRoute"]
-path = components/mizuRoute
-url = https://github.com/ESCOMP/mizuRoute
+ path = components/mizuroute
+ url = https://github.com/ESCOMP/mizuRoute
fxtag = cesm-coupling.n03_v2.2.0
fxrequired = ToplevelRequired
# Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed
diff --git a/README b/README
index 99c6d8e9d4..d678aa9771 100644
--- a/README
+++ b/README
@@ -66,7 +66,7 @@ components/cmeps -------------------- CESM top level driver (for NUOPC driver [w
components/cdeps -------------------- CESM top level data model shared code (for NUOPC driver).
components/cism --------------------- CESM Community land Ice Sheet Model.
components/mosart ------------------- Model for Scale Adaptive River Transport
-components/mizuRoute ---------------- Reached based river transport model for water routing
+components/mizuroute ---------------- Reached based river transport model for water routing
(allows both gridded river and Hydrologic Responce Unit river grids)
components/rtm ---------------------- CESM River Transport Model.
diff --git a/bld/CLMBuildNamelist.pm b/bld/CLMBuildNamelist.pm
index 408ff9b573..c3f1866bf4 100755
--- a/bld/CLMBuildNamelist.pm
+++ b/bld/CLMBuildNamelist.pm
@@ -4071,7 +4071,16 @@ sub setup_logic_fire_emis {
if ( &value_is_true( $nl_flags->{'use_fates'} ) ) {
$log->warning("Fire emission option $var can NOT be on when FATES is also on.\n" .
" DON'T use the '--fire_emis' option when '--bgc fates' is activated");
- }
+ } elsif ( ! &value_is_true( $nl_flags->{'use_cn'} ) ) {
+ $log->fatal_error("Fire emission option $var can NOT be on when BGC SP (i.e. Satellite Phenology) is also on.\n" .
+ " DON'T use the '--fire_emis' option when '--bgc sp' is activated");
+ } elsif ( &value_is_true( $nl_flags->{'use_cn'}) ) {
+ my $fire_method = remove_leading_and_trailing_quotes( $nl->get_value('fire_method') );
+ if ( $fire_method eq "nofire" ) {
+ $log->fatal_error("Fire emission option $var can NOT be on with BGC and fire_method=='nofire'.\n" .
+ " DON'T use the '--fire_emis' option when fire_method is nofire");
+ }
+ }
}
}
}
@@ -4235,7 +4244,7 @@ sub setup_logic_lai_streams {
if ( &value_is_true($nl_flags->{'use_crop'}) && &value_is_true($nl->get_value('use_lai_streams')) ) {
$log->fatal_error("turning use_lai_streams on is incompatable with use_crop set to true.");
}
- if ( $nl_flags->{'bgc_mode'} eq "sp" || ($nl_flags->{'bgc_mode'} eq "fates" && &value_is_true($nl->get_value('use_fates_sp')) )) {
+ if ( $nl_flags->{'bgc_mode'} eq "sp" || ($nl_flags->{'bgc_mode'} eq "fates" && &value_is_true($nl_flags->{'use_fates_sp'}) )) {
if ( &value_is_true($nl->get_value('use_lai_streams')) ) {
add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_lai_streams');
add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'lai_mapalgo',
@@ -4745,29 +4754,26 @@ sub setup_logic_fates {
# For FATES SP mode make sure no-competetiion, and fixed-biogeography are also set
# And also check for other settings that can't be trigged on as well
#
- my $var = "use_fates_sp";
- if ( defined($nl->get_value($var)) ) {
- if ( &value_is_true($nl->get_value($var)) ) {
- my @list = ( "use_fates_nocomp", "use_fates_fixed_biogeog" );
- foreach my $var ( @list ) {
- if ( ! &value_is_true($nl->get_value($var)) ) {
- $log->fatal_error("$var is required when FATES SP is on (use_fates_sp)" );
- }
- }
- # spit-fire can't be on with FATES SP mode is active
- if ( $nl->get_value('fates_spitfire_mode') > 0 ) {
- $log->fatal_error('fates_spitfire_mode can NOT be set to greater than 0 when use_fates_sp is true');
- }
+ if ( &value_is_true($nl_flags->{'use_fates_sp'}) ) {
+ my @list = ( "use_fates_nocomp", "use_fates_fixed_biogeog" );
+ foreach my $var ( @list ) {
+ if ( ! &value_is_true($nl->get_value($var)) ) {
+ $log->fatal_error("$var is required when FATES SP is on (use_fates_sp)" );
+ }
+ }
+ # spit-fire can't be on with FATES SP mode is active
+ if ( $nl->get_value('fates_spitfire_mode') > 0 ) {
+ $log->fatal_error('fates_spitfire_mode can NOT be set to greater than 0 when use_fates_sp is true');
+ }
- # fates landuse can't be on with FATES SP mode is active
- if ( &value_is_true($nl->get_value('use_fates_luh')) ) {
- $log->fatal_error('use_fates_luh can NOT be true when use_fates_sp is true');
- }
+ # fates landuse can't be on with FATES SP mode is active
+ if ( &value_is_true($nl->get_value('use_fates_luh')) ) {
+ $log->fatal_error('use_fates_luh can NOT be true when use_fates_sp is true');
+ }
- # hydro isn't currently supported to work when FATES SP mode is active
- if (&value_is_true( $nl->get_value('use_fates_planthydro') )) {
- $log->fatal_error('fates sp mode is currently not supported to work with fates hydro');
- }
+ # hydro isn't currently supported to work when FATES SP mode is active
+ if (&value_is_true( $nl->get_value('use_fates_planthydro') )) {
+ $log->fatal_error('fates sp mode is currently not supported to work with fates hydro');
}
}
my $var = "use_fates_inventory_init";
@@ -4792,6 +4798,13 @@ sub setup_logic_fates {
}
}
}
+ # Check that both FaTES-SP and FATES ST3 aren't both on
+ my $var = "use_fates_ed_st3";
+ if ( defined($nl->get_value($var)) ) {
+ if ( &value_is_true($nl->get_value($var)) && &value_is_true($nl_flags->{'use_fates_sp'}) ) {
+ $log->fatal_error("$var can NOT also be true with use_fates_sp true" );
+ }
+ }
# check that fates landuse change mode has the necessary luh2 landuse timeseries data
# and add the default if not defined. Do not add default if use_fates_potentialveg is true.
# If fixed biogeography is on, make sure that flandusepftdat is avilable.
diff --git a/bld/namelist_files/namelist_defaults_ctsm.xml b/bld/namelist_files/namelist_defaults_ctsm.xml
index fedfca8020..574b6feec9 100644
--- a/bld/namelist_files/namelist_defaults_ctsm.xml
+++ b/bld/namelist_files/namelist_defaults_ctsm.xml
@@ -1119,6 +1119,12 @@ attributes from the config_cache.xml file (with keys converted to upper-case).
>hgrid=ne0np4.ARCTICGRIS.ne30x8 maxpft=17 mask=tx0.1v2 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false.
+
+hgrid=ne0np4CONUS.ne30x8 maxpft=17 mask=tx0.1v2 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false.
+
+
lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_mpasa120_hist_2000_78pfts_c240908.nc
+
+lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne3np4_hist_2000_78pfts_c240925.nc
lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne3np4.pg3_hist_2000_78pfts_c240908.nc
@@ -1721,6 +1729,8 @@ lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne30np4.pg2_hist_1850_78pfts_c240908.n
lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne30np4.pg3_hist_1850_78pfts_c240908.nc
lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne3np4.pg3_hist_1850_78pfts_c240908.nc
+
+lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne3np4_hist_1850_78pfts_c240925.nc
lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_C96_hist_1850_78pfts_c240908.nc
@@ -1731,8 +1741,6 @@ lnd/clm2/surfdata_esmf/ctsm5.3.0/synthetic/surfdata_1x1_cidadinhoBR_synth_hist_2
lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_1x1_brazil_hist_1850_78pfts_c240912.nc
-
-lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne3np4.pg3_hist_1850_78pfts_c240908.nc
lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne16np4.pg3_hist_1850_78pfts_c240908.nc
@@ -1803,6 +1811,8 @@ lnd/clm2/surfdata_esmf/NEON/ctsm5.3.0/surfdata_1x1_NEON_TOOL_hist_2000_78pfts_c2
lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_mpasa120_SSP2-4.5_1850-2100_78pfts_c240908.nc
+lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_ne3np4_SSP2-4.5_1850-2100_78pfts_c240926.nc
lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_ne3np4.pg3_SSP2-4.5_1850-2100_78pfts_c240908.nc
lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_mpasa120_SSP2-4.5_1850-2100_78pfts_c240908.nc
+lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_ne3np4_SSP2-4.5_1850-2100_78pfts_c240926.nc
lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_ne3np4.pg3_SSP2-4.5_1850-2100_78pfts_c240908.nc
$ntests );
@@ -288,7 +288,7 @@ sub cat_and_create_namelistinfile {
&make_config_cache($phys);
my @mfiles = ( "lnd_in", "drv_flds_in", $tempfile );
my $mfiles = NMLTest::CompFiles->new( $cwd, @mfiles );
-foreach my $options ( "-drydep", "-megan", "-drydep -megan", "-fire_emis", "-drydep -megan -fire_emis" ) {
+foreach my $options ( "-drydep --bgc sp", "-megan --bgc sp", "-drydep -megan --bgc bgc", "-fire_emis --bgc bgc", "-drydep -megan -fire_emis --bgc bgc" ) {
&make_env_run();
eval{ system( "$bldnml -envxml_dir . $options > $tempfile 2>&1 " ); };
is( $@, '', "options: $options" );
@@ -576,8 +576,8 @@ sub cat_and_create_namelistinfile {
"--res 1.9x2.5 --bgc bgc --use_case 1850-2100_SSP2-4.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",
+ "-res 0.9x1.25 -bgc sp -use_case 1850_noanthro_control -drydep",
+ "-res 0.9x1.25 -bgc bgc -use_case 1850_noanthro_control -drydep -fire_emis -megan -light_res 360x720",
"--bgc bgc --light_res none --namelist \"&a fire_method='nofire'/\"",
"--bgc fates --light_res 360x720 --no-megan --namelist \"&a fates_spitfire_mode=2/\"",
"--bgc fates --light_res none --no-megan --namelist \"&a fates_spitfire_mode=1/\"",
@@ -1093,6 +1093,10 @@ sub cat_and_create_namelistinfile {
namelst=>"suplnitro='NONE'",
phys=>"clm6_0",
},
+ "FATESwBothSpST3" =>{ options=>"--bgc fates --envxml_dir . --no-megan",
+ namelst=>"use_fates_sp = TRUE, use_fates_ed_st3 = TRUE",
+ phys=>"clm6_0",
+ },
"FireNoneButBGCfireon" =>{ options=>"-bgc bgc -envxml_dir . -light_res none",
namelst=>"fire_method='li2021gswpfrc'",
phys=>"clm6_0",
@@ -1145,6 +1149,14 @@ sub cat_and_create_namelistinfile {
namelst=>"",
phys=>"clm4_5",
},
+ "useFIREEMISwithNOFIRE" =>{ options=>"--bgc bgc --envxml_dir . --fire_emis",
+ namelst=>"fire_method='nofire'",
+ phys=>"clm6_0",
+ },
+ "useFIREEMISwithSP" =>{ options=>"--bgc sp --envxml_dir . --fire_emis",
+ namelst=>"",
+ phys=>"clm6_0",
+ },
"useDRYDEPwithFATES" =>{ options=>"--bgc fates --envxml_dir . --no-megan --drydep",
namelst=>"",
phys=>"clm4_5",
@@ -1494,7 +1506,7 @@ sub cat_and_create_namelistinfile {
print "========================================================================\n";
# Check for ALL resolutions with CLM50SP
-my @resolutions = ( "360x720cru", "10x15", "4x5", "0.9x1.25", "1.9x2.5", "ne3np4.pg3", "ne16np4.pg3", "ne30np4", "ne30np4.pg2", "ne30np4.pg3", "ne120np4.pg3", "ne0np4CONUS.ne30x8", "ne0np4.ARCTIC.ne30x4", "ne0np4.ARCTICGRIS.ne30x8", "C96", "mpasa480", "mpasa120" );
+my @resolutions = ( "360x720cru", "10x15", "4x5", "0.9x1.25", "1.9x2.5", "ne3np4", "ne3np4.pg3", "ne16np4.pg3", "ne30np4", "ne30np4.pg2", "ne30np4.pg3", "ne120np4.pg3", "ne0np4CONUS.ne30x8", "ne0np4.ARCTIC.ne30x4", "ne0np4.ARCTICGRIS.ne30x8", "C96", "mpasa480", "mpasa120" );
my @only2000_resolutions = ( "1x1_numaIA", "1x1_brazil", "1x1_mexicocityMEX", "1x1_vancouverCAN", "1x1_urbanc_alpha", "5x5_amazon", "0.125nldas2", "mpasa60", "mpasa15", "mpasa3p75" );
my @regional;
foreach my $res ( @resolutions ) {
@@ -1531,7 +1543,7 @@ sub cat_and_create_namelistinfile {
print " Test important resolutions for BGC and historical\n";
print "==================================================\n";
-my @resolutions = ( "4x5", "10x15", "360x720cru", "ne30np4.pg3", "ne3np4.pg3", "1.9x2.5", "0.9x1.25", "C96", "mpasa120" );
+my @resolutions = ( "4x5", "10x15", "360x720cru", "ne30np4.pg3", "ne3np4", "ne3np4.pg3", "1.9x2.5", "0.9x1.25", "C96", "mpasa120" );
my @regional;
my $nlbgcmode = "bgc";
my $mode = "$phys-$nlbgcmode";
@@ -1758,7 +1770,7 @@ sub cat_and_create_namelistinfile {
&cleanup();
}
-my @crop_res = ( "1x1_numaIA", "4x5", "10x15", "0.9x1.25", "1.9x2.5", "ne3np4.pg3", "ne30np4", "ne30np4.pg3", "C96", "mpasa120" );
+my @crop_res = ( "1x1_numaIA", "4x5", "10x15", "0.9x1.25", "1.9x2.5", "ne3np4", "ne3np4.pg3", "ne30np4", "ne30np4.pg3", "C96", "mpasa120" );
foreach my $res ( @crop_res ) {
$options = "-bgc bgc -crop -res $res -envxml_dir .";
&make_env_run();
@@ -1847,7 +1859,7 @@ sub cat_and_create_namelistinfile {
&cleanup();
}
# Transient ssp_rcp scenarios that work
-my @tran_res = ( "4x5", "0.9x1.25", "1.9x2.5", "10x15", "360x720cru", "ne3np4.pg3", "ne16np4.pg3", "ne30np4.pg3", "C96", "mpasa120" );
+my @tran_res = ( "4x5", "0.9x1.25", "1.9x2.5", "10x15", "360x720cru", "ne3np4", "ne3np4.pg3", "ne16np4.pg3", "ne30np4.pg3", "C96", "mpasa120" );
foreach my $usecase ( "1850-2100_SSP2-4.5_transient" ) {
my $startymd = 20150101;
foreach my $res ( @tran_res ) {
@@ -1884,7 +1896,7 @@ sub cat_and_create_namelistinfile {
"-bgc bgc -clm_demand flanduse_timeseries -sim_year 1850-2000 -namelist '&a start_ymd=18500101/'",
"-bgc bgc -envxml_dir . -namelist '&a use_c13=.true.,use_c14=.true.,use_c14_bombspike=.true./'" );
foreach my $clmopts ( @clmoptions ) {
- my @clmres = ( "10x15", "4x5", "360x720cru", "0.9x1.25", "1.9x2.5", "ne3np4.pg3", "ne16np4.pg3", "ne30np4.pg3", "C96", "mpasa120" );
+ my @clmres = ( "10x15", "4x5", "360x720cru", "0.9x1.25", "1.9x2.5", "ne3np4", "ne3np4.pg3", "ne16np4.pg3", "ne30np4.pg3", "C96", "mpasa120" );
foreach my $res ( @clmres ) {
$options = "-res $res -envxml_dir . ";
&make_env_run( );
diff --git a/cime_config/config_component.xml b/cime_config/config_component.xml
index 689fbcde0d..f869d0e362 100644
--- a/cime_config/config_component.xml
+++ b/cime_config/config_component.xml
@@ -241,12 +241,24 @@
char
-
- -bgc sp
- -bgc bgc
- -bgc bgc -crop
- -bgc fates -no-megan
- -bgc fates -no-megan
+
+ -bgc sp
+ -bgc bgc
+ -bgc bgc -crop
+
+
+ --bgc fates --no-megan --no-drydep --no-fire_emis
+
+
+ --bgc sp --no-megan --no-drydep --no-fire_emis
+ --bgc bgc --no-megan --no-drydep --no-fire_emis
+ --bgc bgc --crop --no-megan --no-drydep --no-fire_emis
+
-bgc bgc -dynamic_vegetation
diff --git a/cime_config/testdefs/testlist_clm.xml b/cime_config/testdefs/testlist_clm.xml
index 1a00fb683e..6bb09b5833 100644
--- a/cime_config/testdefs/testlist_clm.xml
+++ b/cime_config/testdefs/testlist_clm.xml
@@ -219,7 +219,7 @@
-
+
@@ -228,7 +228,7 @@
-
+
@@ -406,7 +406,7 @@
-
+
@@ -415,8 +415,18 @@
+
+
+
+
+
+
+
+
+
+
-
+
@@ -425,7 +435,7 @@
-
+
@@ -434,7 +444,7 @@
-
+
@@ -443,7 +453,7 @@
-
+
@@ -453,7 +463,7 @@
-
+
@@ -462,7 +472,7 @@
-
+
@@ -471,7 +481,7 @@
-
+
@@ -480,7 +490,7 @@
-
+
@@ -546,7 +556,7 @@
-
+
@@ -1261,7 +1271,7 @@
-
+
@@ -1289,7 +1299,7 @@
-
+
@@ -1298,7 +1308,7 @@
-
+
@@ -1307,7 +1317,7 @@
-
+
@@ -1316,7 +1326,7 @@
-
+
@@ -1471,6 +1481,8 @@
+
+
@@ -1758,7 +1770,7 @@
-
+
@@ -1776,7 +1788,7 @@
-
+
@@ -1819,6 +1831,7 @@
+
@@ -1827,7 +1840,7 @@
-
+
@@ -1847,7 +1860,7 @@
-
+
@@ -1856,7 +1869,7 @@
-
+
@@ -2007,6 +2020,7 @@
+
@@ -2318,7 +2332,7 @@
-
+
@@ -2444,6 +2458,16 @@
+
+
+
+
+
+
+
+
+
+
@@ -2451,6 +2475,7 @@
+
@@ -2464,6 +2489,17 @@
+
+
+
+
+
+
+
+
+
+
+
@@ -2494,6 +2530,17 @@
+
+
+
+
+
+
+
+
+
+
+
@@ -2542,6 +2589,16 @@
+
+
+
+
+
+
+
+
+
+
@@ -2648,13 +2705,14 @@
-
+
+
-
+
@@ -2679,7 +2737,7 @@
-
+
@@ -2689,6 +2747,7 @@
+
@@ -2822,7 +2881,7 @@
-
+
@@ -2939,6 +2998,16 @@
+
+
+
+
+
+
+
+
+
+
@@ -2952,12 +3021,13 @@
+
-
+
@@ -3554,7 +3624,7 @@
-
+
@@ -3564,7 +3634,7 @@
-
+
@@ -3575,7 +3645,7 @@
-
+
@@ -3948,10 +4018,10 @@
-
+
-
+
@@ -3975,6 +4045,7 @@
+
@@ -3988,6 +4059,7 @@
+
diff --git a/cime_config/testdefs/testmods_dirs/clm/ExcessIceStartup_output_sp_exice/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/ExcessIceStartup_output_sp_exice/include_user_mods
index 142522f5b3..eccf97ff8e 100644
--- a/cime_config/testdefs/testmods_dirs/clm/ExcessIceStartup_output_sp_exice/include_user_mods
+++ b/cime_config/testdefs/testmods_dirs/clm/ExcessIceStartup_output_sp_exice/include_user_mods
@@ -1,2 +1,3 @@
+../nofireemis
../monthly
../../../../usermods_dirs/clm/output_sp_exice
diff --git a/cime_config/testdefs/testmods_dirs/clm/ExcessIceStreams/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/ExcessIceStreams/include_user_mods
index 1e4ddf5337..bc8c80f140 100644
--- a/cime_config/testdefs/testmods_dirs/clm/ExcessIceStreams/include_user_mods
+++ b/cime_config/testdefs/testmods_dirs/clm/ExcessIceStreams/include_user_mods
@@ -1,2 +1,2 @@
-../default
../nofireemis
+../default
\ No newline at end of file
diff --git a/cime_config/testdefs/testmods_dirs/clm/SNICARFRC/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/SNICARFRC/include_user_mods
index 1e4ddf5337..bc8c80f140 100644
--- a/cime_config/testdefs/testmods_dirs/clm/SNICARFRC/include_user_mods
+++ b/cime_config/testdefs/testmods_dirs/clm/SNICARFRC/include_user_mods
@@ -1,2 +1,2 @@
-../default
../nofireemis
+../default
\ No newline at end of file
diff --git a/cime_config/testdefs/testmods_dirs/clm/collapse_pfts_78_to_16_decStart_f10/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/collapse_pfts_78_to_16_decStart_f10/include_user_mods
index acdaa462fc..821b73c2e0 100644
--- a/cime_config/testdefs/testmods_dirs/clm/collapse_pfts_78_to_16_decStart_f10/include_user_mods
+++ b/cime_config/testdefs/testmods_dirs/clm/collapse_pfts_78_to_16_decStart_f10/include_user_mods
@@ -1 +1,2 @@
+../nofireemis
../decStart
diff --git a/cime_config/testdefs/testmods_dirs/clm/o3lombardozzi2015/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/o3lombardozzi2015/include_user_mods
index 1e4ddf5337..d3df58a6b3 100644
--- a/cime_config/testdefs/testmods_dirs/clm/o3lombardozzi2015/include_user_mods
+++ b/cime_config/testdefs/testmods_dirs/clm/o3lombardozzi2015/include_user_mods
@@ -1,2 +1,2 @@
-../default
../nofireemis
+../default
diff --git a/cime_config/testdefs/testmods_dirs/clm/pauseResume/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/pauseResume/include_user_mods
index 1e4ddf5337..d3df58a6b3 100644
--- a/cime_config/testdefs/testmods_dirs/clm/pauseResume/include_user_mods
+++ b/cime_config/testdefs/testmods_dirs/clm/pauseResume/include_user_mods
@@ -1,2 +1,2 @@
-../default
../nofireemis
+../default
diff --git a/cime_config/testdefs/testmods_dirs/clm/prescribed/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/prescribed/include_user_mods
index 1e4ddf5337..bc8c80f140 100644
--- a/cime_config/testdefs/testmods_dirs/clm/prescribed/include_user_mods
+++ b/cime_config/testdefs/testmods_dirs/clm/prescribed/include_user_mods
@@ -1,2 +1,2 @@
-../default
../nofireemis
+../default
\ No newline at end of file
diff --git a/cime_config/testdefs/testmods_dirs/clm/pts/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/pts/include_user_mods
index 1e4ddf5337..d3df58a6b3 100644
--- a/cime_config/testdefs/testmods_dirs/clm/pts/include_user_mods
+++ b/cime_config/testdefs/testmods_dirs/clm/pts/include_user_mods
@@ -1,2 +1,2 @@
-../default
../nofireemis
+../default
diff --git a/cime_config/testdefs/testmods_dirs/clm/waccmx_offline/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/waccmx_offline/include_user_mods
index 1e4ddf5337..d3df58a6b3 100644
--- a/cime_config/testdefs/testmods_dirs/clm/waccmx_offline/include_user_mods
+++ b/cime_config/testdefs/testmods_dirs/clm/waccmx_offline/include_user_mods
@@ -1,2 +1,2 @@
-../default
../nofireemis
+../default
diff --git a/components/mizuRoute b/components/mizuroute
similarity index 100%
rename from components/mizuRoute
rename to components/mizuroute
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 0182e1c991..f16cfe585a 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,4 +1,140 @@
===============================================================
+Tag name: ctsm5.3.059
+Originator(s): erik (Erik Kluzek)
+Date: Mon 23 Jun 2025 01:39:37 AM MDT
+One-line Summary: Bring in various cleanup efforts found in previous testing after the chill changes came in
+
+Purpose and description of changes
+----------------------------------
+
+Various updates for testing and other problems identified in the
+cesm3_0_beta04 tag. So fixes and cleanup for usability.
+Including the following:
+
+- Fix SHR_ASSERT so single-point matrix test passes
+- ne3np4 to namelist_defaults_ctsm.xml and Makefile for PTS mode and add ability
+- Fixes warm starts in PTS_MODE so that SCAM can use restart files
+- f19 + f45 16pft fsurdat/landuse files to namelist_defaults_ctsm + Makefile
+- Changes in the FORTRAN code to properly abort when fire-emission is asked for
+ it can't be provided. Added unit testing for this.
+
+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.)
+
+ [Put an [X] in the box for any configuration with significant answer changes.]
+
+[ ] clm6_0
+
+[ ] clm5_0
+
+[ ] ctsm5_0-nwp
+
+[ ] clm4_5
+
+
+Bugs fixed
+----------
+List of CTSM issues fixed (include CTSM Issue # and description) [one per line]:
+
+ Fixes #2868 -- Custom crop calendar instructions
+ Fixes #2791 -- f19 16 pft for PPE work
+ Fixes #2768 -- ne3np4 added in
+ Fixes #2780 -- CN matrix single point
+ Fixes #2762 -- Don't allow FATES, SP, or nofire to turn fire-emis on
+ Fixes #3073 -- Wrong order for testmods with nofireemis
+ Some of #2810 -- 16pft f45 landuse.timeseries for FATES
+ CTSM namelist checking for:
+ https://github.com/NGEET/fates/issues/1356 -- FatesSp and FATES ST3 on at same time
+ Some work on https://github.com/ESCOMP/CTSM/issues/2643 -- standarize logical settings for FATES
+
+Notes of particular relevance for users
+---------------------------------------
+Caveats for users (e.g., need to interpolate initial conditions):
+ Turning on fire-emissions can NOT be turned on now for configurations that
+ don't allow it.
+ - FATES
+ - Sp
+ - Bgc but with nofire
+
+ Also now CTSM fire-emiss, drydep and MEGAN are turned off for CTSM when coupled to CAM
+ This means that CAM will be the one that sets each of these
+ They can be added and turned on for CTSM I compsets though
+
+Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables):
+ FATES-SP and FATES-ST3 can't be both on at the same time
+
+Changes made to namelist defaults (e.g., changed parameter values):
+ Changes to some of the finidat file settings for 2013 at ne0np4CONUS.ne30x8
+
+Changes to the datasets (e.g., parameter, surface or initial files):
+ New fsurdat/flanduse_timeseries for ne3np4 needed for SCAM
+
+Notes of particular relevance for developers:
+---------------------------------------------
+Caveats for developers (e.g., code that is duplicated that requires double maintenance):
+ Path for mizuroute changed to lowercase so that it matches CESM checkouts
+
+Changes to tests or testing:
+ Many tests now need to explicitly set nofireemis. Some testmods that assume
+ Sp include that explicitly. Other tests also include --clm-nofireemis
+ PTS_MODE testing changed from f45 to ne3np4 for SCAM
+ Add more tests for CAM VR grids
+ Add more namelist testing for ne3np4 and for fire-emission options and
+ FatesSp and FATES ST3 mode fails correctly
+
+
+Testing summary: regular, ctsm_sci
+----------------
+ [PASS means all tests PASS; OK means tests PASS other than expected fails.]
+
+ build-namelist tests (if CLMBuildNamelist.pm has changed):
+
+ derecho - OK
+
+ python testing (if python code has changed; see instructions in python/README.md; document testing done):
+
+ derecho - Fails, but ctsm5.3.058 does as well
+
+ regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing):
+
+ derecho ----- OK
+ izumi ------- OK
+
+ any other testing (give details below):
+
+ ctsm_sci
+ derecho ---- OK
+ cesm_testing:
+ SMS_D_Ln9.f19_f19_mg17.FWma2000climo.derecho_intel.cam-outfrq9s_waccm_ma_mam4
+ SMS_D_Ln9.ne0ARCTICne30x4_ne0ARCTICne30x4_mt12.FHIST.derecho_intel.cam-outfrq9s
+ SMS_D_Ln9_P1280x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCHIST.derecho_intel.cam-outfrq9s
+ SMS_D_Ln9_P1280x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCnudged.derecho_intel.cam-outfrq9s
+ SMS_D_Ln9_P5120x1.ne0ARCTICne30x4_ne0ARCTICne30x4_mt12.FHIST.derecho_intel.cam-outfrq9s
+
+Answer changes
+--------------
+
+Changes answers relative to baseline: no-bit-for-bit
+ Some tests that allowed fire-emissions to be on, have a different field list now
+
+Other details
+-------------
+
+List any git submodules updated (cime, rtm, mosart, cism, fates, etc.):
+ Change name of components/mizuroute directory so the same as used in CESM
+
+Pull Requests that document the changes (include PR ids):
+(https://github.com/ESCOMP/ctsm/pull)
+ #2840 -- Fix single point matrixcn fails
+ #2835 -- n3np4 + warm start fixes for PTS_MODE
+ #2834 -- f19 + f45 16 pft datasets
+ #2844 -- Fortran code abort when fire-emission asked for and can't be provided
+
+===============================================================
+===============================================================
Tag name: ctsm5.3.058
Originator(s): samrabin (Sam Rabin, UCAR/TSS)
Date: Mon Jun 16 11:43:52 MDT 2025
diff --git a/doc/ChangeSum b/doc/ChangeSum
index 7cd6fdf8e6..f5bfed6ef6 100644
--- a/doc/ChangeSum
+++ b/doc/ChangeSum
@@ -1,5 +1,6 @@
Tag Who Date Summary
============================================================================================================================
+ ctsm5.3.059 erik 06/23/2025 Bring in various cleanup efforts found in previous testing after the chill changes came in
ctsm5.3.058 samrabin 06/16/2025 Fix clm6 compset aliases
ctsm5.3.057 glemieux 06/13/2025 Fix PEM test for on-the-fly parameter file generation
ctsm5.3.056 erik 06/12/2025 Merge b4b-dev to master
diff --git a/parse_cime.cs.status b/parse_cime.cs.status
index daaaef2293..eb5c140df9 100755
--- a/parse_cime.cs.status
+++ b/parse_cime.cs.status
@@ -328,13 +328,17 @@ sub print_categories {
my $scrdir = shift(@_);
my %csstatus = @_;
- my $expectedfailfile = "$scrdir/components/clm/cime_config/testdefs/ExpectedTestFails.xml";
- if ( ! -f $expectedfailfile ) {
- $expectedfailfile = "$scrdir/cime_config/testdefs/ExpectedTestFails.xml";
+ my $srcroot = "$scrdir";
+ my $expectedfailfile = "$srcroot/cime_config/testdefs/ExpectedTestFails.xml";
+ if ( $srcroot =~ m|/components/clm$|) {
+ $srcroot = absolute_path( "$scrdir/../.." );
+ if ( ! -f $expectedfailfile ) {
+ die "ERROR: CTSM ExpectedTestFails.xml file NOT found in $scrdir\n";
+ }
}
- my @failfiles = ( $expectedfailfile, "$scrdir/components/mizuRoute/cime_config/testdefs/ExpectedTestFails.xml",
- #"$scrdir/components/mosart/cime_config/testdefs/ExpectedTestFails.xml",
- "$scrdir/components/cmeps/cime_config/ExpectedTestFails.xml" );
+ my @failfiles = ( $expectedfailfile, "$srcroot/components/mizuroute/cime_config/testdefs/ExpectedTestFails.xml",
+ "$srcroot/components/mosart/cime_config/testdefs/ExpectedTestFails.xml",
+ "$srcroot/components/cmeps/cime_config/ExpectedTestFails.xml" );
my @passes;
my @fails;
my @pendings;
diff --git a/python/ctsm/toolchain/gen_mksurfdata_jobscript_multi.py b/python/ctsm/toolchain/gen_mksurfdata_jobscript_multi.py
index 14957a0177..5a5425dc60 100755
--- a/python/ctsm/toolchain/gen_mksurfdata_jobscript_multi.py
+++ b/python/ctsm/toolchain/gen_mksurfdata_jobscript_multi.py
@@ -203,11 +203,11 @@ def main():
"ultra_hi_res_no_crop": ["mpasa15", "mpasa3p75"],
"standard_res": ["360x720cru", "0.9x1.25", "1.9x2.5", "C96", "mpasa120"],
"standard_res_no_f09": ["360x720cru", "1.9x2.5", "C96", "mpasa120"],
- "low_res": ["4x5", "10x15", "ne3np4.pg3"],
+ "low_res": ["4x5", "10x15", "ne3np4.pg3", "ne3np4"],
"mpasa480": ["mpasa480"],
"nldas_res": ["0.125nldas2"],
"5x5_amazon": ["5x5_amazon"],
- "ne3": ["ne3np4.pg3"],
+ "ne3": ["ne3np4", "ne3np4.pg3"],
"ne16": ["ne16np4.pg3"],
"ne30": ["ne30np4.pg3", "ne30np4.pg2", "ne30np4"],
"ne0np4": [
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9707af4f0b..2682775ca5 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -45,6 +45,8 @@ add_subdirectory(${CLM_ROOT}/share/unit_test_stubs/util csm_share_stubs)
list ( APPEND drv_sources_needed
${CLM_ROOT}/components/cmeps/cesm/nuopc_cap_share/glc_elevclass_mod.F90
${CLM_ROOT}/components/cmeps/cesm/nuopc_cap_share/shr_dust_emis_mod.F90
+ ${CLM_ROOT}/components/cmeps/cesm/nuopc_cap_share/shr_expr_parser_mod.F90
+ ${CLM_ROOT}/components/cmeps/cesm/nuopc_cap_share/shr_fire_emis_mod.F90
)
# Add CLM source directories
diff --git a/src/biogeochem/CMakeLists.txt b/src/biogeochem/CMakeLists.txt
index 270e85838b..3da0a2eab6 100644
--- a/src/biogeochem/CMakeLists.txt
+++ b/src/biogeochem/CMakeLists.txt
@@ -2,6 +2,7 @@
# source files that are currently used in unit tests
list(APPEND clm_sources
+ ch4varcon.F90
CNSharedParamsMod.F90
CNPhenologyMod.F90
CNSpeciesMod.F90
@@ -12,6 +13,14 @@ list(APPEND clm_sources
DustEmisFactory.F90
CropReprPoolsMod.F90
CropType.F90
+ CNFireBaseMod.F90
+ CNFireNoFireMod.F90
+ CNFireFactoryMod.F90
+ CNFireLi2014Mod.F90
+ CNFireLi2016Mod.F90
+ CNFireLi2021Mod.F90
+ CNFireLi2024Mod.F90
+ CNVegMatrixMod.F90
CNVegStateType.F90
CNVegCarbonStateType.F90
CNVegCarbonFluxType.F90
@@ -20,6 +29,11 @@ list(APPEND clm_sources
CNVegNitrogenFluxType.F90
CNCIsoAtmTimeSeriesReadMod.F90
CNVegComputeSeedMod.F90
+ FATESFireBase.F90
+ FATESFireDataMod.F90
+ FATESFireFactoryMod.F90
+ FATESFireNoDataMod.F90
+ SatellitePhenologyMod.F90
SpeciesBaseType.F90
SpeciesIsotopeType.F90
SpeciesNonIsotopeType.F90
diff --git a/src/biogeochem/CNDriverMod.F90 b/src/biogeochem/CNDriverMod.F90
index b407e07ad5..9a51d9f616 100644
--- a/src/biogeochem/CNDriverMod.F90
+++ b/src/biogeochem/CNDriverMod.F90
@@ -60,7 +60,7 @@ module CNDriverMod
contains
!-----------------------------------------------------------------------
- subroutine CNDriverInit(bounds, NLFilename, cnfire_method)
+ subroutine CNDriverInit(bounds, NLFilename)
!
! !DESCRIPTION:
! Initialzation of the CN Ecosystem dynamics.
@@ -68,18 +68,15 @@ subroutine CNDriverInit(bounds, NLFilename, cnfire_method)
! !USES:
use CNSharedParamsMod , only : use_fun
use CNPhenologyMod , only : CNPhenologyInit
- use FireMethodType , only : fire_method_type
use SoilBiogeochemCompetitionMod, only : SoilBiogeochemCompetitionInit
!
! !ARGUMENTS:
type(bounds_type) , intent(in) :: bounds
character(len=*) , intent(in) :: NLFilename ! Namelist filename
- class(fire_method_type) , intent(inout) :: cnfire_method
!-----------------------------------------------------------------------
call SoilBiogeochemCompetitionInit(bounds)
if(use_cn)then
call CNPhenologyInit(bounds)
- call cnfire_method%FireInit(bounds, NLFilename)
end if
end subroutine CNDriverInit
diff --git a/src/biogeochem/CNFireBaseMod.F90 b/src/biogeochem/CNFireBaseMod.F90
index 2f9e99ea44..42a054b44c 100644
--- a/src/biogeochem/CNFireBaseMod.F90
+++ b/src/biogeochem/CNFireBaseMod.F90
@@ -85,13 +85,17 @@ module CNFireBaseMod
private
! !PRIVATE MEMBER DATA:
! !PUBLIC MEMBER DATA (used by extensions of the base class):
- real(r8), public, pointer :: btran2_patch (:) ! patch root zone soil wetness factor (0 to 1)
+ real(r8), public, pointer :: btran2_patch (:) => NULL() ! patch root zone soil wetness factor (0 to 1)
contains
!
! !PUBLIC MEMBER FUNCTIONS:
+ procedure, public :: CNFireInit ! Initialization of Fire
procedure, public :: FireInit => CNFireInit ! Initialization of Fire
- procedure, public :: FireReadNML ! Read in namelist for CNFire
+ procedure, public :: CNFireCleanBase ! Deallocate fire data
+ procedure, public :: FireClean => CNFireCleanBase ! Deallocate fire data
+ procedure, public :: CNFireReadNML ! Read in namelist for CNFire
+ procedure, public :: FireReadNML => CNFireReadNML ! Read in namelist for CNFire
procedure, public :: CNFireReadParams ! Read in constant parameters from the paramsfile
procedure, public :: CNFireFluxes ! Calculate fire fluxes
procedure, public :: CNFire_calc_fire_root_wetness_Li2014 ! Calculate CN-fire specific root wetness: original version
@@ -129,17 +133,16 @@ end function need_lightning_and_popdens_interface
contains
!-----------------------------------------------------------------------
- subroutine CNFireInit( this, bounds, NLFilename )
+ subroutine CNFireInit( this, bounds )
!
! !DESCRIPTION:
! Initialize CN Fire module
! !ARGUMENTS:
class(cnfire_base_type) :: this
type(bounds_type), intent(in) :: bounds
- character(len=*), intent(in) :: NLFilename
!-----------------------------------------------------------------------
! Call the base-class Initialization method
- call this%BaseFireInit( bounds, NLFilename )
+ call this%BaseFireInit( bounds )
! Allocate memory
call this%InitAllocate( bounds )
@@ -185,6 +188,24 @@ subroutine InitHistory( this, bounds )
ptr_patch=this%btran2_patch, l2g_scale_type='veg')
end subroutine InitHistory
+ !----------------------------------------------------------------------
+
+ subroutine CNFireCleanBase( this )
+ !
+ ! Deallocate data
+ !
+ ! !ARGUMENTS:
+ class(cnfire_base_type) :: this
+ !-----------------------------------------------------------------------
+ ! Call the base class clean method
+ !call this%BaseFireClean()
+
+ if ( associated(this%btran2_patch) )then
+ deallocate(this%btran2_patch)
+ end if
+ this%btran2_patch => NULL()
+ end subroutine CNFireCleanBase
+
!----------------------------------------------------------------------
subroutine CNFire_calc_fire_root_wetness_Li2014( this, bounds, &
num_exposedvegp, filter_exposedvegp, num_noexposedvegp, filter_noexposedvegp, &
@@ -321,7 +342,7 @@ end subroutine CNFire_calc_fire_root_wetness_Li2021
!----------------------------------------------------------------------
!----------------------------------------------------------------------
- subroutine FireReadNML( this, NLFilename )
+ subroutine CNFireReadNML( this, bounds, NLFilename )
!
! !DESCRIPTION:
! Read the namelist for CNFire
@@ -331,17 +352,17 @@ subroutine FireReadNML( this, NLFilename )
use shr_nl_mod , only : shr_nl_find_group_name
use spmdMod , only : masterproc, mpicom
use shr_mpi_mod , only : shr_mpi_bcast
- use clm_varctl , only : iulog
!
! !ARGUMENTS:
class(cnfire_base_type) :: this
+ type(bounds_type), intent(in):: bounds !bounds
character(len=*), intent(in) :: NLFilename ! Namelist filename
!
! !LOCAL VARIABLES:
integer :: ierr ! error code
integer :: unitn ! unit for namelist file
- character(len=*), parameter :: subname = 'FireReadNML'
+ character(len=*), parameter :: subname = 'CNFireReadNML'
character(len=*), parameter :: nmlname = 'lifire_inparm'
!-----------------------------------------------------------------------
real(r8) :: cli_scale, boreal_peatfire_c, pot_hmn_ign_counts_alpha
@@ -361,6 +382,9 @@ subroutine FireReadNML( this, NLFilename )
borpeat_fire_soilmoist_denom, nonborpeat_fire_precip_denom
if ( this%need_lightning_and_popdens() ) then
+ ! Read the base namelist
+ call this%BaseFireReadNML( bounds, NLFilename )
+
cli_scale = cnfire_const%cli_scale
boreal_peatfire_c = cnfire_const%boreal_peatfire_c
non_boreal_peatfire_c = cnfire_const%non_boreal_peatfire_c
@@ -392,9 +416,11 @@ subroutine FireReadNML( this, NLFilename )
read(unitn, nml=lifire_inparm, iostat=ierr)
if (ierr /= 0) then
call endrun(msg="ERROR reading "//nmlname//"namelist"//errmsg(sourcefile, __LINE__))
+ return
end if
else
call endrun(msg="ERROR could NOT find "//nmlname//"namelist"//errmsg(sourcefile, __LINE__))
+ return
end if
call relavu( unitn )
end if
@@ -447,7 +473,7 @@ subroutine FireReadNML( this, NLFilename )
end if
end if
- end subroutine FireReadNML
+ end subroutine CNFireReadNML
!-----------------------------------------------------------------------
subroutine CNFireFluxes (this, bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, &
diff --git a/src/biogeochem/CNFireFactoryMod.F90 b/src/biogeochem/CNFireFactoryMod.F90
index 44407da927..9d1962d4ff 100644
--- a/src/biogeochem/CNFireFactoryMod.F90
+++ b/src/biogeochem/CNFireFactoryMod.F90
@@ -9,17 +9,20 @@ module CNFireFactoryMod
use abortutils , only : endrun
use shr_log_mod , only : errMsg => shr_log_errMsg
use clm_varctl , only : iulog
+ use shr_kind_mod , only : CS => SHR_KIND_CS
implicit none
save
private
!
! !PUBLIC ROUTINES:
- public :: CNFireReadNML ! read the fire namelist
+ public :: CNFireReadNML ! read the fire factory namelist to get the CN fire_method to use
public :: create_cnfire_method ! create an object of class fire_method_type
+ ! For Unit Testing:
+ public :: CNFireSetFireMethod ! Set the fire_method
! !PRIVATE DATA MEMBERS:
- character(len=80), private :: fire_method = "li2014qianfrc"
+ character(len=CS), private :: fire_method = "UNSET"
character(len=*), parameter, private :: sourcefile = &
__FILE__
@@ -63,9 +66,11 @@ subroutine CNFireReadNML( NLFilename )
read(unitn, nml=cnfire_inparm, iostat=ierr)
if (ierr /= 0) then
call endrun(msg="ERROR reading "//nmlname//"namelist"//errmsg(sourcefile, __LINE__))
+ return
end if
else
call endrun(msg="ERROR finding "//nmlname//"namelist"//errmsg(sourcefile, __LINE__))
+ return
end if
call relavu( unitn )
end if
@@ -82,7 +87,7 @@ end subroutine CNFireReadNML
!-----------------------------------------------------------------------
!-----------------------------------------------------------------------
- subroutine create_cnfire_method( NLFilename, cnfire_method )
+ subroutine create_cnfire_method( cnfire_method )
!
! !DESCRIPTION:
! Create and return an object of fire_method_type. The particular type
@@ -98,11 +103,9 @@ subroutine create_cnfire_method( NLFilename, cnfire_method )
use decompMod , only : bounds_type
!
! !ARGUMENTS:
- character(len=*), intent(in) :: NLFilename ! Namelist filename
class(fire_method_type), allocatable, intent(inout) :: cnfire_method
!
! !LOCAL VARIABLES:
- character(len=*), parameter :: subname = 'create_cnfire_method'
!-----------------------------------------------------------------------
select case (trim(fire_method))
@@ -119,13 +122,29 @@ subroutine create_cnfire_method( NLFilename, cnfire_method )
allocate(cnfire_li2024_type :: cnfire_method)
case default
- write(iulog,*) subname//' ERROR: unknown method: ', fire_method
- call endrun(msg=errMsg(sourcefile, __LINE__))
+ write(iulog,*) 'Unrecognized fire_method ' // errMsg(sourcefile, __LINE__)
+ call endrun( msg='Unknown option for namelist item fire_method: ' // trim(fire_method) )
+ ! For unit-testing, make sure a valid cnfire_method is set and return, otherwise it fails with a seg-fault
+ allocate(cnfire_nofire_type :: cnfire_method)
+ return
end select
- call cnfire_method%FireReadNML( NLFilename )
end subroutine create_cnfire_method
!-----------------------------------------------------------------------
+ subroutine CNFireSetFireMethod( fire_method_in )
+ !
+ ! !DESCRIPTION:
+ ! Set the fire_method (to be used in unit testing)
+ !
+ ! !USES:
+ ! !ARGUMENTS:
+ character(len=*), intent(IN) :: fire_method_in
+
+ fire_method = trim(fire_method_in)
+
+ end subroutine CNFireSetFireMethod
+ !-----------------------------------------------------------------------
+
end module CNFireFactoryMod
diff --git a/src/biogeochem/CNFireNoFireMod.F90 b/src/biogeochem/CNFireNoFireMod.F90
index e0605585e9..da6f28cd0d 100644
--- a/src/biogeochem/CNFireNoFireMod.F90
+++ b/src/biogeochem/CNFireNoFireMod.F90
@@ -8,6 +8,8 @@ module CNFireNoFireMod
!
! !USES:
use shr_kind_mod , only : r8 => shr_kind_r8
+ use abortutils , only : endrun
+ use clm_varctl , only : iulog
use decompMod , only : bounds_type
use atm2lndType , only : atm2lnd_type
use CNVegStateType , only : cnveg_state_type
@@ -36,10 +38,15 @@ module CNFireNoFireMod
contains
!
! !PUBLIC MEMBER FUNCTIONS:
- procedure, public :: need_lightning_and_popdens
- procedure, public :: CNFireArea ! Calculate fire area
+ procedure, public :: need_lightning_and_popdens ! If need lightning and/or population density (always .false. here)
+ procedure, public :: NoFireInit ! Initiialization
+ procedure, public :: FireInit => NoFireInit ! Initiialization
+ procedure, public :: CNFireArea ! Calculate fire area
end type cnfire_nofire_type
+ character(len=*), parameter, private :: sourcefile = &
+ __FILE__
+
contains
!-----------------------------------------------------------------------
@@ -56,6 +63,28 @@ function need_lightning_and_popdens(this)
need_lightning_and_popdens = .false.
end function need_lightning_and_popdens
+ !-----------------------------------------------------------------------
+ subroutine NoFireInit( this, bounds )
+ !
+ ! !DESCRIPTION:
+ ! Initialize No Fire module
+ use shr_fire_emis_mod, only : shr_fire_emis_mechcomps_n
+ use shr_log_mod , only : errMsg => shr_log_errMsg
+ ! !ARGUMENTS:
+ class(cnfire_nofire_type) :: this
+ type(bounds_type), intent(in) :: bounds
+
+ if ( shr_fire_emis_mechcomps_n > 0) then
+ write(iulog,*) "Fire emissions can NOT be active for fire_method=nofire" // &
+ errMsg(sourcefile, __LINE__)
+ call endrun(msg="Having fire emissions on requires fire_method to be something besides nofire" )
+ return
+ end if
+ call this%CNFireInit( bounds )
+
+ end subroutine NoFireInit
+ !-----------------------------------------------------------------------
+
!-----------------------------------------------------------------------
subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, &
num_exposedvegp, filter_exposedvegp, num_noexposedvegp, filter_noexposedvegp, &
diff --git a/src/biogeochem/CNVegetationFacade.F90 b/src/biogeochem/CNVegetationFacade.F90
index 47099708f4..b47237690d 100644
--- a/src/biogeochem/CNVegetationFacade.F90
+++ b/src/biogeochem/CNVegetationFacade.F90
@@ -204,10 +204,12 @@ subroutine Init(this, bounds, NLFilename, nskip_steps, params_ncid)
!
! !USES:
use CNFireFactoryMod , only : create_cnfire_method
+ use CNFireNoFireMod , only : cnfire_nofire_type
use clm_varcon , only : c13ratio, c14ratio
use ncdio_pio , only : file_desc_t
use filterMod , only : filter
use decompMod , only : get_proc_clumps
+
!
! !ARGUMENTS:
class(cn_vegetation_type), intent(inout) :: this
@@ -302,10 +304,21 @@ subroutine Init(this, bounds, NLFilename, nskip_steps, params_ncid)
! use_cndv is true so that it can be used in associate statements (nag compiler
! complains otherwise)
call this%dgvs_inst%Init(bounds)
- end if
- call create_cnfire_method(NLFilename, this%cnfire_method)
- call this%cnfire_method%CNFireReadParams( params_ncid )
+ call create_cnfire_method( this%cnfire_method )
+ call this%cnfire_method%FireInit( bounds )
+ call this%cnfire_method%FireReadNML( bounds, NLFilename )
+ call this%cnfire_method%CNFireReadParams( params_ncid )
+ end if
+
+ !
+ ! For FATES we HAVE to allocate a cnfire_method even through it won't be used
+ ! cnfire_method is passed down to CN routines that are used for FATES
+ ! so there has to be something allocated that is passed down
+ !
+ if ( use_fates_bgc )then
+ allocate(cnfire_nofire_type :: this%cnfire_method)
+ end if
end subroutine Init
@@ -584,7 +597,7 @@ subroutine Init2(this, bounds, NLFilename)
character(len=*), parameter :: subname = 'Init2'
!-----------------------------------------------------------------------
- call CNDriverInit(bounds, NLFilename, this%cnfire_method)
+ call CNDriverInit(bounds, NLFilename)
if (use_cndv) then
call dynCNDV_init(bounds, this%dgvs_inst)
diff --git a/src/biogeochem/FATESFireFactoryMod.F90 b/src/biogeochem/FATESFireFactoryMod.F90
index 0352994e5f..94e3eee4c3 100644
--- a/src/biogeochem/FATESFireFactoryMod.F90
+++ b/src/biogeochem/FATESFireFactoryMod.F90
@@ -42,7 +42,8 @@ subroutine create_fates_fire_data_method( fates_fire_data_method )
! The particular type is determined based on a namelist parameter.
!
! !USES:
- use clm_varctl, only: fates_spitfire_mode
+ use clm_varctl, only: fates_spitfire_mode, use_fates_sp, use_fates_ed_st3
+ use shr_fire_emis_mod, only : shr_fire_emis_mechcomps_n
use FATESFireBase, only: fates_fire_base_type
use FATESFireNoDataMod, only: fates_fire_no_data_type
use FATESFireDataMod, only: fates_fire_data_type
@@ -51,25 +52,69 @@ subroutine create_fates_fire_data_method( fates_fire_data_method )
class(fates_fire_base_type), allocatable, intent(inout) :: fates_fire_data_method ! function result
!
! !LOCAL VARIABLES:
- integer :: current_case
-
- character(len=*), parameter :: subname = 'create_fates_fire_data_method'
!-----------------------------------------------------------------------
- current_case = fates_spitfire_mode
-
- select case (current_case)
+ !
+ ! For FATES options that bypass fire...
+ !
+ if ( use_fates_sp .or. use_fates_ed_st3 )then
+ !
+ ! Make sure fire-emissions is NOT on
+ !
+ if ( shr_fire_emis_mechcomps_n > 0 )then
+ if ( use_fates_sp )then
+ write(iulog,*) "Fire emissions can NOT be on with FATES-SP mode: ", &
+ errMsg(sourcefile, __LINE__)
+ call endrun(msg="Fire emission with FATES requires FATES to NOT be in Satellite Phenology (SP) mode" )
+ else if ( use_fates_ed_st3 )then
+ write(iulog,*) "Fire emissions can NOT be on with FATES ST3 mode: ", &
+ errMsg(sourcefile, __LINE__)
+ call endrun(msg="Fire emission with FATES requires FATES to NOT be in Static Stand Structure mode" )
+ end if
+ ! For unit-testing return with a FATESFireData type, so there isn't a run-time error
+ ! Also do the FATESFireData type, as using FATESFireNoData type will fail with an error
+ allocate(fates_fire_data_type :: fates_fire_data_method)
+ return
+ end if
+ allocate(fates_fire_no_data_type :: fates_fire_data_method)
+ else
+ !
+ ! For regular FATES options that include fire
+ !
+ select case (fates_spitfire_mode)
- case (no_fire:scalar_lightning)
- allocate(fates_fire_no_data_type :: fates_fire_data_method)
- case (lightning_from_data:anthro_suppression)
- allocate(fates_fire_data_type :: fates_fire_data_method)
+ ! No-fire, scalar-lightning and successful_ignitions ALL do NOT need input data from the base class
+ case (no_fire:scalar_lightning)
+ allocate(fates_fire_no_data_type :: fates_fire_data_method)
+ case (successful_ignitions)
+ allocate(fates_fire_no_data_type :: fates_fire_data_method)
+ ! Lightning from data, and the anthro types (ignition and suppression) need lightning data from the base class
+ case (lightning_from_data)
+ allocate(fates_fire_data_type :: fates_fire_data_method)
+ case (anthro_ignitions:anthro_suppression)
+ allocate(fates_fire_data_type :: fates_fire_data_method)
- case default
- write(iulog,*) subname//' ERROR: unknown method: ', fates_spitfire_mode
- call endrun(msg=errMsg(sourcefile, __LINE__))
+ case default
+ write(iulog,*) 'Unrecognized fates_spitfire_mode option = ', fates_spitfire_mode, ' in: ', &
+ errMsg(sourcefile, __LINE__)
+ call endrun(msg="Unknown option for namelist item fates_spitfire_mode:")
+ ! For unit-testing, make sure a valid fates_fire_data_method is set and return, otherwise it fails with a seg-fault
+ allocate(fates_fire_no_data_type :: fates_fire_data_method)
- end select
+ end select
+ ! -------------------------------------------------------------------------------------------------------
+ ! For now we die with a error whenever fire-emissions are turned on -- because this isn't setup in FATES
+ !
+ if ( fates_spitfire_mode /= no_fire ) then
+ if ( shr_fire_emis_mechcomps_n > 0 )then
+ write(iulog,*) "Fire emissions can NOT be on with FATES currently: ", &
+ errMsg(sourcefile, __LINE__)
+ call endrun(msg="Fire emission with FATES can NOT currently be turned on (see issue #1045)" )
+ return
+ end if
+ end if
+ ! -------------------------------------------------------------------------------------------------------
+ end if
end subroutine create_fates_fire_data_method
diff --git a/src/biogeochem/FATESFireNoDataMod.F90 b/src/biogeochem/FATESFireNoDataMod.F90
index 4034b68e97..65b7bae5af 100644
--- a/src/biogeochem/FATESFireNoDataMod.F90
+++ b/src/biogeochem/FATESFireNoDataMod.F90
@@ -27,6 +27,8 @@ module FATESFireNoDataMod
contains
! !PUBLIC MEMBER FUNCTIONS:
+ procedure, public :: FATESNoFireInit! Initialization
+ procedure, public :: FireInit => FATESNoFireInit
procedure, public :: need_lightning_and_popdens
procedure, public :: GetLight24 ! Return the 24-hour averaged lightning data
procedure, public :: GetGDP ! Return the global gdp data
@@ -40,6 +42,28 @@ module FATESFireNoDataMod
contains
+ !-----------------------------------------------------------------------
+ subroutine FATESNoFireInit( this, bounds )
+ !
+ ! !DESCRIPTION:
+ ! Initialize No Fire data module for FATES
+ use shr_fire_emis_mod, only : shr_fire_emis_mechcomps_n
+ use shr_log_mod , only : errMsg => shr_log_errMsg
+ use clm_varctl , only : fates_spitfire_mode
+ ! !ARGUMENTS:
+ class(fates_fire_no_data_type) :: this
+ type(bounds_type), intent(in) :: bounds
+
+ if ( (shr_fire_emis_mechcomps_n > 0) .and. (fates_spitfire_mode == 0) ) then
+ write(iulog,*) "Fire emissions can NOT be active for fates_spitfire_mode=0 (no_fire)", &
+ errMsg(sourcefile, __LINE__)
+ call endrun(msg="Having fire emissions on requires fates_spitfire_mode to be something besides no_fire (0)" )
+ return
+ end if
+ call this%CNFireInit( bounds )
+
+ end subroutine FATESNoFireInit
+
!------------------------------------------------------------------------
function need_lightning_and_popdens(this)
! !ARGUMENTS:
diff --git a/src/biogeochem/SatellitePhenologyMod.F90 b/src/biogeochem/SatellitePhenologyMod.F90
index a6d5fde22d..7747aad5fa 100644
--- a/src/biogeochem/SatellitePhenologyMod.F90
+++ b/src/biogeochem/SatellitePhenologyMod.F90
@@ -13,12 +13,13 @@ module SatellitePhenologyMod
use shr_log_mod , only : errMsg => shr_log_errMsg
use decompMod , only : bounds_type
use abortutils , only : endrun
- use clm_varctl , only : iulog, use_lai_streams
+ use clm_varctl , only : iulog, use_lai_streams, single_column
use perf_mod , only : t_startf, t_stopf
use spmdMod , only : masterproc, mpicom, iam
use laiStreamMod , only : lai_init, lai_advance, lai_interp
use clm_varctl , only : use_fates
- use ncdio_pio
+ use ncdio_pio , only : ncd_pio_openfile, ncd_inqfdims, check_dim_size, ncd_io
+ use ncdio_pio , only : ncd_pio_closefile, file_desc_t
!
! !PUBLIC TYPES:
implicit none
@@ -56,6 +57,9 @@ subroutine SatellitePhenologyInit (bounds)
!
! !USES:
use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=)
+ use shr_fire_emis_mod, only : shr_fire_emis_mechcomps_n
+ use shr_log_mod, only : errMsg => shr_log_errMsg
+ use clm_varctl, only : use_cn
!
! !ARGUMENTS:
type(bounds_type), intent(in) :: bounds
@@ -63,6 +67,12 @@ subroutine SatellitePhenologyInit (bounds)
! !LOCAL VARIABLES:
integer :: ier ! error code
!-----------------------------------------------------------------------
+ if ( (shr_fire_emis_mechcomps_n > 0) .and. (.not. use_cn) ) then
+ write(iulog,*) "Fire emissions can NOT be active for Satellite Phenology mode (SP)" // &
+ errMsg(sourcefile, __LINE__)
+ call endrun(msg="Fire emission requires BGC to be on rather than a Satelitte Pheonology (SP) case")
+ return
+ end if
InterpMonths1 = -999 ! saved month index
@@ -363,7 +373,7 @@ subroutine readAnnualVegetation (bounds, canopystate_inst)
call ncd_pio_openfile (ncid, trim(locfn), 0)
call ncd_inqfdims (ncid, isgrid2d, ni, nj, ns)
- if (ldomain%ns /= ns .or. ldomain%ni /= ni .or. ldomain%nj /= nj) then
+ if (.not. single_column .and. (ldomain%ns /= ns .or. ldomain%ni /= ni .or. ldomain%nj /= nj)) then
write(iulog,*)trim(subname), 'ldomain and input file do not match dims '
write(iulog,*)trim(subname), 'ldomain%ni,ni,= ',ldomain%ni,ni
write(iulog,*)trim(subname), 'ldomain%nj,nj,= ',ldomain%nj,nj
diff --git a/src/biogeochem/test/CMakeLists.txt b/src/biogeochem/test/CMakeLists.txt
index e22a720523..2ebe27c76f 100644
--- a/src/biogeochem/test/CMakeLists.txt
+++ b/src/biogeochem/test/CMakeLists.txt
@@ -3,3 +3,5 @@ add_subdirectory(CNVegComputeSeed_test)
add_subdirectory(CNPhenology_test)
add_subdirectory(Latbaset_test)
add_subdirectory(DustEmis_test)
+add_subdirectory(CNFireFactory_test)
+add_subdirectory(FATESFireFactory_test)
diff --git a/src/biogeochem/test/CNFireFactory_test/CMakeLists.txt b/src/biogeochem/test/CNFireFactory_test/CMakeLists.txt
new file mode 100644
index 0000000000..032e0fa953
--- /dev/null
+++ b/src/biogeochem/test/CNFireFactory_test/CMakeLists.txt
@@ -0,0 +1,7 @@
+set (pfunit_sources
+ test_CNFireFactory.pf
+)
+
+add_pfunit_ctest(CNFireFActory
+ TEST_SOURCES "${pfunit_sources}"
+ LINK_LIBRARIES clm csm_share esmf)
diff --git a/src/biogeochem/test/CNFireFactory_test/test_CNFireFactory.pf b/src/biogeochem/test/CNFireFactory_test/test_CNFireFactory.pf
new file mode 100644
index 0000000000..5b0f52c8d4
--- /dev/null
+++ b/src/biogeochem/test/CNFireFactory_test/test_CNFireFactory.pf
@@ -0,0 +1,240 @@
+module test_CNFireFactory
+
+ ! Tests of CNFireFactory
+
+ use funit
+ use unittestSubgridMod, only : bounds
+ use FireMethodType , only : fire_method_type
+ use CNFireFactoryMod
+ use ESMF, only : ESMF_SUCCESS
+ use shr_kind_mod , only : r8 => shr_kind_r8
+ use clm_varctl, only : use_cn, iulog
+
+ implicit none
+
+ @TestCase
+ type, extends(TestCase) :: TestCNFireFactory
+ logical :: initialized = .false.
+ class(fire_method_type), allocatable :: cnfire_method
+ contains
+ procedure :: setUp
+ procedure :: tearDown
+ procedure :: FireFactInit
+ procedure :: turn_fire_emis_on
+ end type TestCNFireFactory
+
+ contains
+
+ !-----------------------------------------------------------------------
+
+ subroutine setUp(this)
+ use shr_log_mod, only : shr_log_setLogUnit
+ use ESMF, only : ESMF_Initialize, ESMF_IsInitialized
+ use shr_sys_mod, only : shr_sys_system
+ class(TestCNFireFactory), intent(inout) :: this
+
+ integer :: rc
+ logical :: esmf_initialized
+
+ esmf_initialized = ESMF_IsInitialized( rc=rc )
+ if (rc /= ESMF_SUCCESS) then
+ stop 'Error in ESMF_IsInitialized'
+ end if
+ if ( .not. esmf_initialized )then
+ call ESMF_Initialize( rc=rc )
+ if (rc /= ESMF_SUCCESS) then
+ stop 'Error in ESMF_Initialize'
+ end if
+ end if
+ use_cn = .true.
+ iulog = 6
+ call shr_log_setLogUnit(iulog)
+ this%initialized = .false.
+
+ end subroutine setUp
+ !-----------------------------------------------------------------------
+
+ subroutine tearDown(this)
+ use shr_sys_mod, only : shr_sys_system
+ use shr_log_mod, only : shr_log_setLogUnit
+ class(TestCNFireFactory), intent(inout) :: this
+
+ integer :: rc
+
+ ! A clean method should be added to the fire method class structures
+ if ( this%initialized )then
+ call this%cnfire_method%FireClean()
+ deallocate( this%cnfire_method )
+ end if
+ ! IMPORTANT NOTE: DO NOT CALL ESMF_Finalize HERE!
+ ! Calling ESMF_Finalize here, with full ESMF, means you couldn't call ESMF_Initialize again
+ this%initialized = .false.
+
+ end subroutine tearDown
+
+ !-----------------------------------------------------------------------
+
+ subroutine FireFactInit(this, fire_method)
+ class(TestCNFireFactory), intent(inout) :: this
+ character(len=*), intent(in) :: fire_method
+
+ if ( trim(fire_method) /= "DO_NOT_SET") then
+ call CNFireSetFireMethod( fire_method_in=fire_method )
+ end if
+ call create_cnfire_method(this%cnfire_method)
+ call this%cnfire_method%FireInit(bounds)
+ this%initialized = .true.
+
+ end subroutine FireFactInit
+
+ !-----------------------------------------------------------------------
+
+ subroutine turn_fire_emis_on(this)
+ use shr_fire_emis_mod, only : shr_fire_emis_readnl, shr_fire_emis_mechcomps_n
+ use shr_sys_mod, only : shr_sys_system
+ class(TestCNFireFactory), intent(inout) :: this
+
+ ! NOTE!: This is bad that this can be done directly without having it done through a namelist, or setter!
+ shr_fire_emis_mechcomps_n = 2
+ end subroutine turn_fire_emis_on
+
+ !-----------------------------------------------------------------------
+
+ @Test
+ subroutine fire_method_not_set_fails(this)
+ class(TestCNFireFactory), intent(inout) :: this
+ character(100) :: expected_msg
+
+ call this%FireFactInit( fire_method = "DO_NOT_SET")
+ expected_msg = "ABORTED: Unknown option for namelist item fire_method: UNSET"
+ @assertExceptionRaised(expected_msg)
+
+ end subroutine fire_method_not_set_fails
+
+ !-----------------------------------------------------------------------
+
+ @Test
+ subroutine fire_method_bad_fails(this)
+ class(TestCNFireFactory), intent(inout) :: this
+ character(100) :: expected_msg
+
+ call this%FireFactInit( fire_method = "ZZTOP") ! Set to an invalid option
+ expected_msg = "ABORTED: Unknown option for namelist item fire_method: ZZTOP"
+ @assertExceptionRaised(expected_msg)
+
+ end subroutine fire_method_bad_fails
+
+ !-----------------------------------------------------------------------
+
+ @Test
+ subroutine nofire_with_fire_emis_fails(this)
+ class(TestCNFireFactory), intent(inout) :: this
+ character(100) :: expected_msg
+
+ call this%turn_fire_emis_on()
+ call this%FireFactInit( fire_method = "nofire")
+ expected_msg = "ABORTED: Having fire emissions on requires fire_method to be something besides nofire"
+ @assertExceptionRaised(expected_msg)
+
+ end subroutine nofire_with_fire_emis_fails
+
+ !-----------------------------------------------------------------------
+
+ @Test
+ subroutine spcase_with_fire_emis_fails(this)
+ use SatellitePhenologyMod, only : SatellitePhenologyInit
+ class(TestCNFireFactory), intent(inout) :: this
+ character(100) :: expected_msg
+
+ use_cn = .false.
+ call this%turn_fire_emis_on()
+ call SatellitePhenologyInit( bounds )
+ expected_msg = "ABORTED: Fire emission requires BGC to be on rather than a Satelitte Pheonology (SP) case"
+ @assertExceptionRaised(expected_msg)
+
+ end subroutine spcase_with_fire_emis_fails
+
+ !-----------------------------------------------------------------------
+
+ @Test
+ subroutine li2014_works(this)
+ class(TestCNFireFactory), intent(inout) :: this
+
+ call this%FireFactInit( fire_method = "li2014qianfrc")
+
+ end subroutine li2014_works
+
+ !-----------------------------------------------------------------------
+
+ !
+ ! Test that default settings with ALL of the Li Fire options work by default
+ ! (These tests are done one by one which makes them dead simple, but take up more code
+ ! see the looping option below)
+ !
+ @Test
+ subroutine li2016_works(this)
+ class(TestCNFireFactory), intent(inout) :: this
+
+ call this%FireFactInit( fire_method = "li2016crufrc")
+
+ end subroutine li2016_works
+
+ !-----------------------------------------------------------------------
+
+ @Test
+ subroutine li2021_works(this)
+ class(TestCNFireFactory), intent(inout) :: this
+
+ call this%FireFactInit( fire_method = "li2021gswpfrc")
+
+ end subroutine li2021_works
+
+ !-----------------------------------------------------------------------
+
+ @Test
+ subroutine li2024_works(this)
+ class(TestCNFireFactory), intent(inout) :: this
+
+ call this%FireFactInit( fire_method = "li2024gswpfrc")
+
+ end subroutine li2024_works
+
+ !-----------------------------------------------------------------------
+
+ @Test
+ subroutine li2024crujra_works(this)
+ class(TestCNFireFactory), intent(inout) :: this
+
+ call this%FireFactInit( fire_method = "li2024crujra")
+
+ end subroutine li2024crujra_works
+
+ !-----------------------------------------------------------------------
+
+ !
+ ! Test that default settings with ALL of the Li Fire options work when fire emissions
+ ! are turned on. This test is done with a loop rather than one by one as above.
+ ! This cuts down on the total test code, but also means that setUp and tearDown have
+ ! to be explicitly called for example. Setup is always called before a test, and tearDown
+ ! after each test)
+ !
+
+ @Test
+ subroutine all_li_options_with_fire_emis_works(this)
+ class(TestCNFireFactory), intent(inout) :: this
+ integer, parameter :: noptions = 5
+ integer :: i
+ character(len=*), parameter :: fire_method_options(noptions) = (/ 'li2014qianfrc', 'li2016crufrc ', 'li2021gswpfrc', 'li2024gswpfrc', 'li2024crujra '/)
+
+ do i = 1, noptions
+ call this%setUp() ! This is needed because of the loop over all options
+ call this%turn_fire_emis_on()
+ call this%FireFactInit( fire_method = fire_method_options(i) )
+ call this%tearDown() ! This is needed because of the loop over all options
+ end do
+
+ end subroutine all_li_options_with_fire_emis_works
+
+ !-----------------------------------------------------------------------
+
+end module test_CNFireFactory
diff --git a/src/biogeochem/test/FATESFireFactory_test/CMakeLists.txt b/src/biogeochem/test/FATESFireFactory_test/CMakeLists.txt
new file mode 100644
index 0000000000..80ac4114e7
--- /dev/null
+++ b/src/biogeochem/test/FATESFireFactory_test/CMakeLists.txt
@@ -0,0 +1,7 @@
+set (pfunit_sources
+ test_FATESFireFactory.pf
+)
+
+add_pfunit_ctest(FATESFireFActory
+ TEST_SOURCES "${pfunit_sources}"
+ LINK_LIBRARIES clm csm_share esmf)
diff --git a/src/biogeochem/test/FATESFireFactory_test/test_FATESFireFactory.pf b/src/biogeochem/test/FATESFireFactory_test/test_FATESFireFactory.pf
new file mode 100644
index 0000000000..fba39098a8
--- /dev/null
+++ b/src/biogeochem/test/FATESFireFactory_test/test_FATESFireFactory.pf
@@ -0,0 +1,167 @@
+module test_FATESFireFactory
+
+ ! Tests of FATESFireFactory
+
+ use funit
+ use unittestSubgridMod, only : bounds
+ use FATESFireBase, only : fates_fire_base_type
+ use FATESFireFactoryMod
+ use shr_kind_mod , only : r8 => shr_kind_r8, CS => shr_kind_CS
+ use clm_varctl, only : iulog, fates_spitfire_mode, use_fates, use_fates_sp, use_fates_ed_st3
+
+ implicit none
+
+ @TestCase
+ type, extends(TestCase) :: TestFATESFireFactory
+ logical :: initialized = .false.
+ class(fates_fire_base_type), allocatable :: fates_fire_method
+ contains
+ procedure :: setUp
+ procedure :: tearDown
+ procedure :: FireFactInit
+ procedure :: turn_fire_emis_on
+ end type TestFATESFireFactory
+
+ contains
+
+ !-----------------------------------------------------------------------
+
+ subroutine setUp(this)
+ use shr_log_mod, only : shr_log_setLogUnit
+ use ESMF, only : ESMF_Initialize
+ use shr_sys_mod, only : shr_sys_system
+ class(TestFATESFireFactory), intent(inout) :: this
+
+ call ESMF_Initialize()
+ use_fates = .true.
+ use_fates_sp = .false.
+ use_fates_ed_st3 = .false.
+ fates_spitfire_mode = no_fire
+ iulog = 6
+ call shr_log_setLogUnit(iulog)
+ this%initialized = .false.
+
+ end subroutine setUp
+ !-----------------------------------------------------------------------
+
+ subroutine tearDown(this)
+ use shr_sys_mod, only : shr_sys_system
+ use shr_log_mod, only : shr_log_setLogUnit
+ class(TestFATESFireFactory), intent(inout) :: this
+
+ if ( this%initialized )then
+ call this%fates_fire_method%FireClean()
+ deallocate( this%fates_fire_method )
+ end if
+ this%initialized = .false.
+
+ end subroutine tearDown
+
+ !-----------------------------------------------------------------------
+
+ subroutine FireFactInit(this)
+ class(TestFATESFireFactory), intent(inout) :: this
+
+ call create_fates_fire_data_method(this%fates_fire_method)
+ call this%fates_fire_method%FireInit(bounds)
+ this%initialized = .true.
+
+ end subroutine FireFactInit
+
+ !-----------------------------------------------------------------------
+
+ subroutine turn_fire_emis_on(this)
+ use shr_fire_emis_mod, only : shr_fire_emis_readnl, shr_fire_emis_mechcomps_n
+ use shr_sys_mod, only : shr_sys_system
+ class(TestFATESFireFactory), intent(inout) :: this
+
+ ! NOTE!: This is bad that this can be done directly without having it done through a namelist, or setter!
+ shr_fire_emis_mechcomps_n = 2
+ end subroutine turn_fire_emis_on
+
+ !-----------------------------------------------------------------------
+
+ @Test
+ subroutine fates_spitfire_mode_bad_fails(this)
+ class(TestFATESFireFactory), intent(inout) :: this
+ character(100) :: expected_msg
+
+ fates_spitfire_mode = -1
+ call this%FireFactInit( )
+ expected_msg = "ABORTED: Unknown option for namelist item fates_spitfire_mode:"
+ @assertExceptionRaised(expected_msg)
+
+ end subroutine fates_spitfire_mode_bad_fails
+
+ !-----------------------------------------------------------------------
+
+ @Test
+ subroutine fates_sp_case_with_fire_emis_fails(this)
+ use clm_varctl, only : use_fates_sp
+ class(TestFATESFireFactory), intent(inout) :: this
+ character(100) :: expected_msg
+
+ use_fates_sp = .true.
+ call this%turn_fire_emis_on()
+ call this%FireFactInit( )
+ expected_msg = "ABORTED: Fire emission with FATES requires FATES to NOT be in Satellite Phenology (SP) mode"
+ @assertExceptionRaised(expected_msg)
+
+ end subroutine fates_sp_case_with_fire_emis_fails
+
+ !-----------------------------------------------------------------------
+
+ @Test
+ subroutine fates_st3_case_with_fire_emis_fails(this)
+ use clm_varctl, only : use_fates_ed_st3
+ class(TestFATESFireFactory), intent(inout) :: this
+ character(100) :: expected_msg
+
+ use_fates_ed_st3 = .true.
+ call this%turn_fire_emis_on()
+ call this%FireFactInit( )
+ expected_msg = "ABORTED: Fire emission with FATES requires FATES to NOT be in Static Stand Structure mode"
+ @assertExceptionRaised(expected_msg)
+
+ end subroutine fates_st3_case_with_fire_emis_fails
+
+ !-----------------------------------------------------------------------
+
+ @Test
+ subroutine fates_no_spitfire_case_with_fire_emis_fails(this)
+ class(TestFATESFireFactory), intent(inout) :: this
+ character(100) :: expected_msg
+
+ call this%turn_fire_emis_on()
+ fates_spitfire_mode = no_fire
+ call this%FireFactInit( )
+ expected_msg = "ABORTED: Having fire emissions on requires fates_spitfire_mode to be something besides no_fire (0)"
+ @assertExceptionRaised(expected_msg)
+
+ end subroutine fates_no_spitfire_case_with_fire_emis_fails
+
+ !-----------------------------------------------------------------------
+
+ @Test
+ subroutine all_fates_spitfire_options_with_fire_emis_fails(this)
+ class(TestFATESFireFactory), intent(inout) :: this
+ integer, parameter :: noptions = anthro_suppression
+ integer :: i
+ character(100) :: expected_msg
+
+ do i = scalar_lightning, noptions
+ call this%setUp()
+ call this%turn_fire_emis_on()
+ fates_spitfire_mode = i
+ use_fates_sp = .false.
+ call this%FireFactInit( )
+ expected_msg = "ABORTED: Fire emission with FATES can NOT currently be turned on (see issue #1045)"
+ @assertExceptionRaised(expected_msg)
+ call this%tearDown()
+ end do
+
+ end subroutine all_fates_spitfire_options_with_fire_emis_fails
+
+ !-----------------------------------------------------------------------
+
+end module test_FATESFireFactory
diff --git a/src/biogeophys/UrbanParamsType.F90 b/src/biogeophys/UrbanParamsType.F90
index 4b7b80e4fe..c6443897fe 100644
--- a/src/biogeophys/UrbanParamsType.F90
+++ b/src/biogeophys/UrbanParamsType.F90
@@ -9,9 +9,9 @@ module UrbanParamsType
use shr_log_mod , only : errMsg => shr_log_errMsg
use abortutils , only : endrun
use decompMod , only : bounds_type, subgrid_level_gridcell, subgrid_level_landunit
- use clm_varctl , only : iulog, fsurdat
+ use clm_varctl , only : iulog, fsurdat, single_column
use clm_varcon , only : grlnd, spval
- use LandunitType , only : lun
+ use LandunitType , only : lun
!
implicit none
save
@@ -26,21 +26,21 @@ module UrbanParamsType
!
! !PRIVATE TYPE
type urbinp_type
- real(r8), pointer :: canyon_hwr (:,:)
- real(r8), pointer :: wtlunit_roof (:,:)
- real(r8), pointer :: wtroad_perv (:,:)
- real(r8), pointer :: em_roof (:,:)
- real(r8), pointer :: em_improad (:,:)
- real(r8), pointer :: em_perroad (:,:)
- real(r8), pointer :: em_wall (:,:)
- real(r8), pointer :: alb_roof_dir (:,:,:)
- real(r8), pointer :: alb_roof_dif (:,:,:)
- real(r8), pointer :: alb_improad_dir (:,:,:)
- real(r8), pointer :: alb_improad_dif (:,:,:)
- real(r8), pointer :: alb_perroad_dir (:,:,:)
- real(r8), pointer :: alb_perroad_dif (:,:,:)
- real(r8), pointer :: alb_wall_dir (:,:,:)
- real(r8), pointer :: alb_wall_dif (:,:,:)
+ real(r8), pointer :: canyon_hwr (:,:)
+ real(r8), pointer :: wtlunit_roof (:,:)
+ real(r8), pointer :: wtroad_perv (:,:)
+ real(r8), pointer :: em_roof (:,:)
+ real(r8), pointer :: em_improad (:,:)
+ real(r8), pointer :: em_perroad (:,:)
+ real(r8), pointer :: em_wall (:,:)
+ real(r8), pointer :: alb_roof_dir (:,:,:)
+ real(r8), pointer :: alb_roof_dif (:,:,:)
+ real(r8), pointer :: alb_improad_dir (:,:,:)
+ real(r8), pointer :: alb_improad_dif (:,:,:)
+ real(r8), pointer :: alb_perroad_dir (:,:,:)
+ real(r8), pointer :: alb_perroad_dif (:,:,:)
+ real(r8), pointer :: alb_wall_dir (:,:,:)
+ real(r8), pointer :: alb_wall_dif (:,:,:)
real(r8), pointer :: ht_roof (:,:)
real(r8), pointer :: wind_hgt_canyon (:,:)
real(r8), pointer :: tk_wall (:,:,:)
@@ -92,14 +92,14 @@ module UrbanParamsType
real(r8), pointer :: eflx_traffic_factor (:) ! lun multiplicative traffic factor for sensible heat flux from urban traffic (-)
contains
- procedure, public :: Init
-
+ procedure, public :: Init
+
end type urbanparams_type
!
! !Urban control variables
- character(len= *), parameter, public :: urban_hac_off = 'OFF'
- character(len= *), parameter, public :: urban_hac_on = 'ON'
- character(len= *), parameter, public :: urban_wasteheat_on = 'ON_WASTEHEAT'
+ character(len= *), parameter, public :: urban_hac_off = 'OFF'
+ character(len= *), parameter, public :: urban_hac_on = 'ON'
+ character(len= *), parameter, public :: urban_wasteheat_on = 'ON_WASTEHEAT'
character(len= 16), public :: urban_hac = urban_hac_off
logical, public :: urban_explicit_ac = .true. ! whether to use explicit, time-varying AC adoption rate
logical, public :: urban_traffic = .false. ! urban traffic fluxes
@@ -112,7 +112,7 @@ module UrbanParamsType
character(len=*), parameter, private :: sourcefile = &
__FILE__
- !-----------------------------------------------------------------------
+ !-----------------------------------------------------------------------
contains
@@ -132,11 +132,11 @@ subroutine Init(this, bounds)
!
! !ARGUMENTS:
class(urbanparams_type) :: this
- type(bounds_type) , intent(in) :: bounds
+ type(bounds_type) , intent(in) :: bounds
!
! !LOCAL VARIABLES:
integer :: j,l,c,p,g ! indices
- integer :: nc,fl,ib ! indices
+ integer :: nc,fl,ib ! indices
integer :: dindx ! urban density type index
integer :: ier ! error status
real(r8) :: sumvf ! sum of view factors for wall or road
@@ -182,12 +182,12 @@ subroutine Init(this, bounds)
allocate(this%em_perroad (begl:endl)) ; this%em_perroad (:) = nan
allocate(this%em_wall (begl:endl)) ; this%em_wall (:) = nan
allocate(this%alb_roof_dir (begl:endl,numrad)) ; this%alb_roof_dir (:,:) = nan
- allocate(this%alb_roof_dif (begl:endl,numrad)) ; this%alb_roof_dif (:,:) = nan
- allocate(this%alb_improad_dir (begl:endl,numrad)) ; this%alb_improad_dir (:,:) = nan
- allocate(this%alb_perroad_dir (begl:endl,numrad)) ; this%alb_perroad_dir (:,:) = nan
- allocate(this%alb_improad_dif (begl:endl,numrad)) ; this%alb_improad_dif (:,:) = nan
- allocate(this%alb_perroad_dif (begl:endl,numrad)) ; this%alb_perroad_dif (:,:) = nan
- allocate(this%alb_wall_dir (begl:endl,numrad)) ; this%alb_wall_dir (:,:) = nan
+ allocate(this%alb_roof_dif (begl:endl,numrad)) ; this%alb_roof_dif (:,:) = nan
+ allocate(this%alb_improad_dir (begl:endl,numrad)) ; this%alb_improad_dir (:,:) = nan
+ allocate(this%alb_perroad_dir (begl:endl,numrad)) ; this%alb_perroad_dir (:,:) = nan
+ allocate(this%alb_improad_dif (begl:endl,numrad)) ; this%alb_improad_dif (:,:) = nan
+ allocate(this%alb_perroad_dif (begl:endl,numrad)) ; this%alb_perroad_dif (:,:) = nan
+ allocate(this%alb_wall_dir (begl:endl,numrad)) ; this%alb_wall_dir (:,:) = nan
allocate(this%alb_wall_dif (begl:endl,numrad)) ; this%alb_wall_dif (:,:) = nan
allocate(this%eflx_traffic_factor (begl:endl)) ; this%eflx_traffic_factor (:) = nan
@@ -261,7 +261,7 @@ subroutine Init(this, bounds)
! | \ vsr / | | r | | \ vww / s
! | \ / | h o w | \ / k
! wall | \ / | wall | a | | \ / y
- ! |vwr \ / vwr| | d | |vrw \ / vsw
+ ! |vwr \ / vwr| | d | |vrw \ / vsw
! ------\/------ - - |-----\/-----
! road wall |
! <----- w ----> |
@@ -272,20 +272,20 @@ subroutine Init(this, bounds)
! vsw = view factor of sky for wall
! vsr + vwr + vwr = 1 vrw + vww + vsw = 1
!
- ! Source: Masson, V. (2000) A physically-based scheme for the urban energy budget in
+ ! Source: Masson, V. (2000) A physically-based scheme for the urban energy budget in
! atmospheric models. Boundary-Layer Meteorology 94:357-397
!
! - Calculate urban land unit aerodynamic constants using Macdonald (1998) as used in
! Grimmond and Oke (1999)
! ---------------------------------------------------------------------------------------
-
- ! road -- sky view factor -> 1 as building height -> 0
+
+ ! road -- sky view factor -> 1 as building height -> 0
! and -> 0 as building height -> infinity
this%vf_sr(l) = sqrt(lun%canyon_hwr(l)**2 + 1._r8) - lun%canyon_hwr(l)
this%vf_wr(l) = 0.5_r8 * (1._r8 - this%vf_sr(l))
- ! one wall -- sky view factor -> 0.5 as building height -> 0
+ ! one wall -- sky view factor -> 0.5 as building height -> 0
! and -> 0 as building height -> infinity
this%vf_sw(l) = 0.5_r8 * (lun%canyon_hwr(l) + 1._r8 - sqrt(lun%canyon_hwr(l)**2+1._r8)) / lun%canyon_hwr(l)
@@ -311,7 +311,7 @@ subroutine Init(this, bounds)
! Grimmond and Oke (1999)
!----------------------------------------------------------------------------------
- ! Calculate plan area index
+ ! Calculate plan area index
plan_ai = lun%canyon_hwr(l)/(lun%canyon_hwr(l) + 1._r8)
! Building shape shortside/longside ratio (e.g. 1 = square )
@@ -344,7 +344,7 @@ subroutine Init(this, bounds)
(1 - lun%z_d_town(l) / lun%ht_roof(l)) * frontal_ai)**(-0.5_r8))
end if
- else ! Not urban point
+ else ! Not urban point
this%eflx_traffic_factor(l) = spval
this%t_building_min(l) = spval
@@ -366,7 +366,7 @@ end subroutine Init
!-----------------------------------------------------------------------
subroutine UrbanInput(begg, endg, mode)
!
- ! !DESCRIPTION:
+ ! !DESCRIPTION:
! Allocate memory and read in urban input data
!
! !USES:
@@ -375,7 +375,7 @@ subroutine UrbanInput(begg, endg, mode)
use fileutils , only : getavu, relavu, getfil, opnfil
use spmdMod , only : masterproc
use domainMod , only : ldomain
- use ncdio_pio , only : file_desc_t, ncd_io, ncd_inqvdlen, ncd_inqfdims
+ use ncdio_pio , only : file_desc_t, ncd_io, ncd_inqvdlen, ncd_inqfdims
use ncdio_pio , only : ncd_pio_openfile, ncd_pio_closefile, ncd_inqdid, ncd_inqdlen
!
! !ARGUMENTS:
@@ -392,7 +392,7 @@ subroutine UrbanInput(begg, endg, mode)
integer :: numrad_i ! input grid: number of solar bands (VIS/NIR)
integer :: numurbl_i ! input grid: number of urban landunits
integer :: ier,ret ! error status
- logical :: isgrid2d ! true => file is 2d
+ logical :: isgrid2d ! true => file is 2d
logical :: readvar ! true => variable is on dataset
logical :: has_numurbl ! true => numurbl dimension is on dataset
character(len=32) :: subname = 'UrbanInput' ! subroutine name
@@ -403,11 +403,11 @@ subroutine UrbanInput(begg, endg, mode)
if (mode == 'initialize') then
! Read urban data
-
+
if (masterproc) then
write(iulog,*)' Reading in urban input data from fsurdat file ...'
end if
-
+
call getfil (fsurdat, locfn, 0)
call ncd_pio_openfile (ncid, locfn, 0)
@@ -428,20 +428,20 @@ subroutine UrbanInput(begg, endg, mode)
if ( nlevurb == 0 ) return
! Allocate dynamic memory
- allocate(urbinp%canyon_hwr(begg:endg, numurbl), &
- urbinp%wtlunit_roof(begg:endg, numurbl), &
+ allocate(urbinp%canyon_hwr(begg:endg, numurbl), &
+ urbinp%wtlunit_roof(begg:endg, numurbl), &
urbinp%wtroad_perv(begg:endg, numurbl), &
- urbinp%em_roof(begg:endg, numurbl), &
- urbinp%em_improad(begg:endg, numurbl), &
- urbinp%em_perroad(begg:endg, numurbl), &
- urbinp%em_wall(begg:endg, numurbl), &
- urbinp%alb_roof_dir(begg:endg, numurbl, numrad), &
- urbinp%alb_roof_dif(begg:endg, numurbl, numrad), &
- urbinp%alb_improad_dir(begg:endg, numurbl, numrad), &
- urbinp%alb_perroad_dir(begg:endg, numurbl, numrad), &
- urbinp%alb_improad_dif(begg:endg, numurbl, numrad), &
- urbinp%alb_perroad_dif(begg:endg, numurbl, numrad), &
- urbinp%alb_wall_dir(begg:endg, numurbl, numrad), &
+ urbinp%em_roof(begg:endg, numurbl), &
+ urbinp%em_improad(begg:endg, numurbl), &
+ urbinp%em_perroad(begg:endg, numurbl), &
+ urbinp%em_wall(begg:endg, numurbl), &
+ urbinp%alb_roof_dir(begg:endg, numurbl, numrad), &
+ urbinp%alb_roof_dif(begg:endg, numurbl, numrad), &
+ urbinp%alb_improad_dir(begg:endg, numurbl, numrad), &
+ urbinp%alb_perroad_dir(begg:endg, numurbl, numrad), &
+ urbinp%alb_improad_dif(begg:endg, numurbl, numrad), &
+ urbinp%alb_perroad_dif(begg:endg, numurbl, numrad), &
+ urbinp%alb_wall_dir(begg:endg, numurbl, numrad), &
urbinp%alb_wall_dif(begg:endg, numurbl, numrad), &
urbinp%ht_roof(begg:endg, numurbl), &
urbinp%wind_hgt_canyon(begg:endg, numurbl), &
@@ -461,7 +461,7 @@ subroutine UrbanInput(begg, endg, mode)
endif
call ncd_inqfdims (ncid, isgrid2d, ni, nj, ns)
- if (ldomain%ns /= ns .or. ldomain%ni /= ni .or. ldomain%nj /= nj) then
+ if (.not. single_column .and. (ldomain%ns /= ns .or. ldomain%ni /= ni .or. ldomain%nj /= nj)) then
write(iulog,*)trim(subname), 'ldomain and input file do not match dims '
write(iulog,*)trim(subname), 'ldomain%ni,ni,= ',ldomain%ni,ni
write(iulog,*)trim(subname), 'ldomain%nj,nj,= ',ldomain%nj,nj
@@ -655,7 +655,7 @@ subroutine UrbanInput(begg, endg, mode)
call ncd_pio_closefile(ncid)
if (masterproc) then
- write(iulog,*)' Sucessfully read urban input data'
+ write(iulog,*)' Sucessfully read urban input data'
write(iulog,*)
end if
@@ -955,7 +955,3 @@ end function IsProgBuildTemp
!-----------------------------------------------------------------------
end module UrbanParamsType
-
-
-
-
diff --git a/src/cpl/share_esmf/FireDataBaseType.F90 b/src/cpl/share_esmf/FireDataBaseType.F90
index b84e3bfa33..13323cd924 100644
--- a/src/cpl/share_esmf/FireDataBaseType.F90
+++ b/src/cpl/share_esmf/FireDataBaseType.F90
@@ -26,23 +26,25 @@ module FireDataBaseType
type, abstract, extends(fire_method_type) :: fire_base_type
private
! !PRIVATE MEMBER DATA:
- real(r8), public, pointer :: forc_hdm(:) ! Human population density
- type(shr_strdata_type) :: sdat_hdm ! Human population density input data stream
- real(r8), public, pointer :: forc_lnfm(:) ! Lightning frequency
- type(shr_strdata_type) :: sdat_lnfm ! Lightning frequency input data stream
+ real(r8), public, pointer :: forc_hdm(:) => NULL() ! Human population density
+ type(shr_strdata_type) :: sdat_hdm ! Human population density input data stream
+ real(r8), public, pointer :: forc_lnfm(:) => NULL() ! Lightning frequency
+ type(shr_strdata_type) :: sdat_lnfm ! Lightning frequency input data stream
- real(r8), public, pointer :: gdp_lf_col(:) ! col global real gdp data (k US$/capita)
- real(r8), public, pointer :: peatf_lf_col(:) ! col global peatland fraction data (0-1)
- integer , public, pointer :: abm_lf_col(:) ! col global peak month of crop fire emissions
+ real(r8), public, pointer :: gdp_lf_col(:) => NULL() ! col global real gdp data (k US$/capita)
+ real(r8), public, pointer :: peatf_lf_col(:) => NULL() ! col global peatland fraction data (0-1)
+ integer , public, pointer :: abm_lf_col(:) => NULL() ! col global peak month of crop fire emissions
contains
!
! !PUBLIC MEMBER FUNCTIONS:
- procedure, public :: FireInit => BaseFireInit ! Initialization of Fire
procedure, public :: BaseFireInit ! Initialization of Fire
+ procedure, public :: FireInit => BaseFireInit ! Initialization of Fire
+ procedure, public :: BaseFireClean ! Clean up data and deallocate data
+ procedure, public :: FireClean => BaseFireClean ! Clean up data and deallocate data
procedure, public :: FireInterp ! Interpolate fire data
- procedure(FireReadNML_interface), public, deferred :: &
- FireReadNML ! Read in namelist for Fire
+ procedure, public :: BaseFireReadNML ! Read in the namelist for fire
+ procedure, public :: ReadFireNML => BaseFireReadNML ! Read in the namelist for fire
procedure(need_lightning_and_popdens_interface), public, deferred :: &
need_lightning_and_popdens ! Returns true if need lightning & popdens
!
@@ -78,7 +80,7 @@ end function need_lightning_and_popdens_interface
contains
!==============================================================================
- subroutine FireReadNML_interface( this, NLFilename )
+ subroutine BaseFireReadNML( this, bounds, NLFilename )
!
! !DESCRIPTION:
! Read the namelist for Fire
@@ -87,11 +89,21 @@ subroutine FireReadNML_interface( this, NLFilename )
!
! !ARGUMENTS:
class(fire_base_type) :: this
+ type(bounds_type), intent(in) :: bounds
character(len=*), intent(in) :: NLFilename ! Namelist filename
- end subroutine FireReadNML_interface
+
+ ! Read the namelists for the fire data and do the preparation needed on them
+ if ( this%need_lightning_and_popdens() ) then
+ call this%hdm_init(bounds, NLFilename)
+ call this%hdm_interp(bounds)
+ call this%lnfm_init(bounds, NLFilename)
+ call this%lnfm_interp(bounds)
+ call this%surfdataread(bounds)
+ end if
+ end subroutine BaseFireReadNML
!================================================================
- subroutine BaseFireInit( this, bounds, NLFilename )
+ subroutine BaseFireInit( this, bounds )
!
! !DESCRIPTION:
! Initialize CN Fire module
@@ -101,9 +113,7 @@ subroutine BaseFireInit( this, bounds, NLFilename )
! !ARGUMENTS:
class(fire_base_type) :: this
type(bounds_type), intent(in) :: bounds
- character(len=*), intent(in) :: NLFilename
!-----------------------------------------------------------------------
-
if ( this%need_lightning_and_popdens() ) then
! Allocate lightning forcing data
allocate( this%forc_lnfm(bounds%begg:bounds%endg) )
@@ -118,16 +128,36 @@ subroutine BaseFireInit( this, bounds, NLFilename )
allocate(this%peatf_lf_col(bounds%begc:bounds%endc))
! Allocates peak month of crop fire emissions
allocate(this%abm_lf_col(bounds%begc:bounds%endc))
-
- call this%hdm_init(bounds, NLFilename)
- call this%hdm_interp(bounds)
- call this%lnfm_init(bounds, NLFilename)
- call this%lnfm_interp(bounds)
- call this%surfdataread(bounds)
end if
end subroutine BaseFireInit
+ !================================================================
+ subroutine BaseFireClean( this )
+ !
+ ! !DESCRIPTION:
+ ! Clean fire data
+ ! !USES:
+ !
+ ! !ARGUMENTS:
+ class(fire_base_type) :: this
+ !-----------------------------------------------------------------------
+
+ if ( this%need_lightning_and_popdens() ) then
+ deallocate( this%forc_lnfm )
+ deallocate( this%forc_hdm )
+ deallocate( this%gdp_lf_col )
+ deallocate( this%peatf_lf_col )
+ deallocate( this%abm_lf_col )
+ this%forc_lnfm => NULL()
+ this%forc_hdm => NULL()
+ this%gdp_lf_col => NULL()
+ this%peatf_lf_col => NULL()
+ this%abm_lf_col => NULL()
+ end if
+
+ end subroutine BaseFireClean
+
!================================================================
subroutine FireInterp(this,bounds)
!
diff --git a/src/init_interp/initInterp.F90 b/src/init_interp/initInterp.F90
index e0d56aed62..c8f80e16ae 100644
--- a/src/init_interp/initInterp.F90
+++ b/src/init_interp/initInterp.F90
@@ -820,13 +820,13 @@ subroutine findMinDist( dimname, begi, endi, bego, endo, ncidi, ncido, &
write(iulog,*)'calling set_subgrid_info for ',trim(dimname), ' for input'
end if
call set_subgrid_info(beg=begi, end=endi, dimname=dimname, use_glob=.true., &
- ncid=ncidi, active=activei, subgrid=subgridi)
+ ncid=ncidi, active=activei, subgrid=subgridi, allow_scm=.false.)
if (masterproc) then
write(iulog,*)'calling set_subgrid_info for ',trim(dimname), ' for output'
end if
call set_subgrid_info(beg=bego, end=endo, dimname=dimname, use_glob=.false., &
- ncid=ncido, active=activeo, subgrid=subgrido)
+ ncid=ncido, active=activeo, subgrid=subgrido, allow_scm=.true.)
select case (interp_method)
case (interp_method_general)
@@ -859,7 +859,7 @@ end subroutine findMinDist
!=======================================================================
- subroutine set_subgrid_info(beg, end, dimname, use_glob, ncid, active, subgrid)
+ subroutine set_subgrid_info(beg, end, dimname, use_glob, ncid, active, subgrid, allow_scm)
! --------------------------------------------------------------------
! arguments
@@ -869,6 +869,7 @@ subroutine set_subgrid_info(beg, end, dimname, use_glob, ncid, active, subgrid)
logical , intent(in) :: use_glob ! if .true., use the 'glob' form of ncd_io
logical , intent(out) :: active(beg:end)
type(subgrid_type) , intent(inout) :: subgrid
+ logical , intent(in) :: allow_scm ! if .true., allow single column model subset of data
!
! local variables
integer :: n
@@ -896,32 +897,32 @@ subroutine set_subgrid_info(beg, end, dimname, use_glob, ncid, active, subgrid)
end if
if (dimname == 'pft') then
- call read_var_double(ncid=ncid, varname='pfts1d_lon' , data=subgrid%lon , dim1name='pft', use_glob=use_glob)
- call read_var_double(ncid=ncid, varname='pfts1d_lat' , data=subgrid%lat , dim1name='pft', use_glob=use_glob)
- call read_var_int(ncid=ncid, varname='pfts1d_itypveg', data=subgrid%ptype, dim1name='pft', use_glob=use_glob)
- call read_var_int(ncid=ncid, varname='pfts1d_itypcol', data=subgrid%ctype, dim1name='pft', use_glob=use_glob)
- call read_var_int(ncid=ncid, varname='pfts1d_ityplun', data=subgrid%ltype, dim1name='pft', use_glob=use_glob)
- call read_var_int(ncid=ncid, varname='pfts1d_active' , data=itemp , dim1name='pft', use_glob=use_glob)
+ call read_var_double(ncid=ncid, varname='pfts1d_lon' , data=subgrid%lon , dim1name='pft', use_glob=use_glob, allow_scm=allow_scm)
+ call read_var_double(ncid=ncid, varname='pfts1d_lat' , data=subgrid%lat , dim1name='pft', use_glob=use_glob, allow_scm=allow_scm)
+ call read_var_int(ncid=ncid, varname='pfts1d_itypveg', data=subgrid%ptype, dim1name='pft', use_glob=use_glob, allow_scm=allow_scm)
+ call read_var_int(ncid=ncid, varname='pfts1d_itypcol', data=subgrid%ctype, dim1name='pft', use_glob=use_glob, allow_scm=allow_scm)
+ call read_var_int(ncid=ncid, varname='pfts1d_ityplun', data=subgrid%ltype, dim1name='pft', use_glob=use_glob, allow_scm=allow_scm)
+ call read_var_int(ncid=ncid, varname='pfts1d_active' , data=itemp , dim1name='pft', use_glob=use_glob, allow_scm=allow_scm)
if (associated(subgrid%topoglc)) then
- call read_var_double(ncid=ncid, varname='pfts1d_topoglc', data=subgrid%topoglc, dim1name='pft', use_glob=use_glob)
+ call read_var_double(ncid=ncid, varname='pfts1d_topoglc', data=subgrid%topoglc, dim1name='pft', use_glob=use_glob, allow_scm=allow_scm)
end if
else if (dimname == 'column') then
- call read_var_double(ncid=ncid, varname='cols1d_lon' , data=subgrid%lon , dim1name='column', use_glob=use_glob)
- call read_var_double(ncid=ncid, varname='cols1d_lat' , data=subgrid%lat , dim1name='column', use_glob=use_glob)
- call read_var_int(ncid=ncid, varname='cols1d_ityp' , data=subgrid%ctype, dim1name='column', use_glob=use_glob)
- call read_var_int(ncid=ncid, varname='cols1d_ityplun', data=subgrid%ltype, dim1name='column', use_glob=use_glob)
- call read_var_int(ncid=ncid, varname='cols1d_active' , data=itemp , dim1name='column', use_glob=use_glob)
+ call read_var_double(ncid=ncid, varname='cols1d_lon' , data=subgrid%lon , dim1name='column', use_glob=use_glob, allow_scm=allow_scm)
+ call read_var_double(ncid=ncid, varname='cols1d_lat' , data=subgrid%lat , dim1name='column', use_glob=use_glob, allow_scm=allow_scm)
+ call read_var_int(ncid=ncid, varname='cols1d_ityp' , data=subgrid%ctype, dim1name='column', use_glob=use_glob, allow_scm=allow_scm)
+ call read_var_int(ncid=ncid, varname='cols1d_ityplun', data=subgrid%ltype, dim1name='column', use_glob=use_glob, allow_scm=allow_scm)
+ call read_var_int(ncid=ncid, varname='cols1d_active' , data=itemp , dim1name='column', use_glob=use_glob, allow_scm=allow_scm)
if (associated(subgrid%topoglc)) then
- call read_var_double(ncid=ncid, varname='cols1d_topoglc', data=subgrid%topoglc, dim1name='column', use_glob=use_glob)
+ call read_var_double(ncid=ncid, varname='cols1d_topoglc', data=subgrid%topoglc, dim1name='column', use_glob=use_glob, allow_scm=allow_scm)
end if
else if (dimname == 'landunit') then
- call read_var_double(ncid=ncid, varname='land1d_lon' , data=subgrid%lon , dim1name='landunit', use_glob=use_glob)
- call read_var_double(ncid=ncid, varname='land1d_lat' , data=subgrid%lat , dim1name='landunit', use_glob=use_glob)
- call read_var_int(ncid=ncid, varname='land1d_ityplun', data=subgrid%ltype, dim1name='landunit', use_glob=use_glob)
- call read_var_int(ncid=ncid, varname='land1d_active' , data=itemp , dim1name='landunit', use_glob=use_glob)
+ call read_var_double(ncid=ncid, varname='land1d_lon' , data=subgrid%lon , dim1name='landunit', use_glob=use_glob, allow_scm=allow_scm)
+ call read_var_double(ncid=ncid, varname='land1d_lat' , data=subgrid%lat , dim1name='landunit', use_glob=use_glob, allow_scm=allow_scm)
+ call read_var_int(ncid=ncid, varname='land1d_ityplun', data=subgrid%ltype, dim1name='landunit', use_glob=use_glob, allow_scm=allow_scm)
+ call read_var_int(ncid=ncid, varname='land1d_active' , data=itemp , dim1name='landunit', use_glob=use_glob, allow_scm=allow_scm)
else if (dimname == 'gridcell') then
- call read_var_double(ncid=ncid, varname='grid1d_lon' , data=subgrid%lon , dim1name='gridcell', use_glob=use_glob)
- call read_var_double(ncid=ncid, varname='grid1d_lat' , data=subgrid%lat , dim1name='gridcell', use_glob=use_glob)
+ call read_var_double(ncid=ncid, varname='grid1d_lon' , data=subgrid%lon , dim1name='gridcell', use_glob=use_glob, allow_scm=allow_scm)
+ call read_var_double(ncid=ncid, varname='grid1d_lat' , data=subgrid%lat , dim1name='gridcell', use_glob=use_glob, allow_scm=allow_scm)
! All gridcells in the restart file are active
itemp(beg:end) = 1
@@ -942,7 +943,7 @@ subroutine set_subgrid_info(beg, end, dimname, use_glob, ncid, active, subgrid)
contains
- subroutine read_var_double(ncid, varname, data, dim1name, use_glob)
+ subroutine read_var_double(ncid, varname, data, dim1name, use_glob, allow_scm)
! Wraps the ncd_io call, providing logic related to whether we're using the 'glob'
! form of ncd_io
type(file_desc_t) , intent(inout) :: ncid
@@ -950,15 +951,29 @@ subroutine read_var_double(ncid, varname, data, dim1name, use_glob)
real(r8), pointer , intent(inout) :: data(:)
character(len=*) , intent(in) :: dim1name
logical , intent(in) :: use_glob ! if .true., use the 'glob' form of ncd_io
+ logical , intent(in) :: allow_scm ! if .true., allow single column model subset of data
+
+ ! local
+ character(16) :: readflag
+
+ if (allow_scm) then
+ readflag='read'
+ else
+ ! Flag to distinguish the times during IC interpolation when running in single column mode but
+ ! need to read the full data grid. Normally single_column means
+ ! "read the data grid and extract the closest column" but
+ ! during IC interpolation you need to read in the full grid to be interpolated regardless of the single_column flag.
+ readflag='read_noscm'
+ endif
if (use_glob) then
- call ncd_io(ncid=ncid, varname=varname, flag='read', data=data)
+ call ncd_io(ncid=ncid, varname=varname, flag=trim(readflag), data=data)
else
- call ncd_io(ncid=ncid, varname=varname, flag='read', data=data, dim1name=dim1name)
+ call ncd_io(ncid=ncid, varname=varname, flag=trim(readflag), data=data, dim1name=dim1name)
end if
end subroutine read_var_double
- subroutine read_var_int(ncid, varname, data, dim1name, use_glob)
+ subroutine read_var_int(ncid, varname, data, dim1name, use_glob, allow_scm)
! Wraps the ncd_io call, providing logic related to whether we're using the 'glob'
! form of ncd_io
type(file_desc_t) , intent(inout) :: ncid
@@ -966,11 +981,25 @@ subroutine read_var_int(ncid, varname, data, dim1name, use_glob)
integer, pointer , intent(inout) :: data(:)
character(len=*) , intent(in) :: dim1name
logical , intent(in) :: use_glob ! if .true., use the 'glob' form of ncd_io
+ logical , intent(in) :: allow_scm ! if .true., allow single column model subset of data
+
+ ! local
+ character(16) :: readflag
+
+ if (allow_scm) then
+ readflag='read'
+ else
+ ! Flag to distinguish the times during IC interpolation when running in single column mode but
+ ! need to read the full data grid. Normally single_column means
+ ! "read the data grid and extract the closest column" but
+ ! during IC interpolation you need to read in the full grid to be interpolated regardless of the single_column flag.
+ readflag='read_noscm'
+ endif
if (use_glob) then
- call ncd_io(ncid=ncid, varname=varname, flag='read', data=data)
+ call ncd_io(ncid=ncid, varname=varname, flag=trim(readflag), data=data)
else
- call ncd_io(ncid=ncid, varname=varname, flag='read', data=data, dim1name=dim1name)
+ call ncd_io(ncid=ncid, varname=varname, flag=trim(readflag), data=data, dim1name=dim1name)
end if
end subroutine read_var_int
@@ -1038,7 +1067,7 @@ subroutine interp_1d_double (varname, varname_i, dimname, begi, endi, bego, endo
end if
allocate (rbufsli(begi:endi), rbufslo(bego:endo))
- call ncd_io(ncid=ncidi, varname=trim(varname_i), flag='read', data=rbufsli)
+ call ncd_io(ncid=ncidi, varname=trim(varname_i), flag='read_noscm', data=rbufsli)
call ncd_io(ncid=ncido, varname=trim(varname), flag='read', data=rbufslo, &
dim1name=dimname)
@@ -1080,7 +1109,7 @@ subroutine interp_1d_int (varname, varname_i, dimname, begi, endi, bego, endo, n
allocate (ibufsli(begi:endi), ibufslo(bego:endo))
- call ncd_io(ncid=ncidi, varname=trim(varname_i), flag='read', &
+ call ncd_io(ncid=ncidi, varname=trim(varname_i), flag='read_noscm', &
data=ibufsli)
call ncd_io(ncid=ncido, varname=trim(varname), flag='read', &
data=ibufslo, dim1name=dimname)
diff --git a/src/init_interp/initInterpMultilevelContainer.F90 b/src/init_interp/initInterpMultilevelContainer.F90
index 5a7b14832a..d26e51c71c 100644
--- a/src/init_interp/initInterpMultilevelContainer.F90
+++ b/src/init_interp/initInterpMultilevelContainer.F90
@@ -732,7 +732,7 @@ subroutine create_snow_interpolators(interp_multilevel_levsno, interp_multilevel
! Read snlsno_source_sgrid
allocate(snlsno_source_sgrid(bounds_source%get_begc() : bounds_source%get_endc()))
- call ncd_io(ncid=ncid_source, varname='SNLSNO', flag='read', &
+ call ncd_io(ncid=ncid_source, varname='SNLSNO', flag='read_noscm', &
data=snlsno_source_sgrid)
snlsno_source_sgrid(:) = abs(snlsno_source_sgrid(:))
diff --git a/src/main/CMakeLists.txt b/src/main/CMakeLists.txt
index 53a6edb8a5..fc324efeb9 100644
--- a/src/main/CMakeLists.txt
+++ b/src/main/CMakeLists.txt
@@ -20,6 +20,7 @@ list(APPEND clm_sources
column_varcon.F90
decompMod.F90
filterColMod.F90
+ FireMethodType.F90
glc2lndMod.F90
glcBehaviorMod.F90
initSubgridMod.F90
diff --git a/src/main/FireMethodType.F90 b/src/main/FireMethodType.F90
index 978450e65f..5f90dea893 100644
--- a/src/main/FireMethodType.F90
+++ b/src/main/FireMethodType.F90
@@ -34,6 +34,9 @@ module FireMethodType
! Figure out the fire fluxes
procedure(CNFireFluxes_interface) , public, deferred :: CNFireFluxes
+ ! Deallocate the fire datasets
+ procedure(FireClean_interface) , public, deferred :: FireClean
+
end type fire_method_type
abstract interface
@@ -52,7 +55,7 @@ module FireMethodType
! consistent between different implementations.
!
!---------------------------------------------------------------------------
- subroutine FireInit_interface(this, bounds, NLFilename )
+ subroutine FireInit_interface(this, bounds )
!
! !DESCRIPTION:
! Initialize Fire datasets
@@ -63,20 +66,21 @@ subroutine FireInit_interface(this, bounds, NLFilename )
! !ARGUMENTS:
class(fire_method_type) :: this
type(bounds_type), intent(in) :: bounds
- character(len=*), intent(in) :: NLFilename
!-----------------------------------------------------------------------
end subroutine FireInit_interface
- subroutine FireReadNML_interface(this, NLFilename )
+ subroutine FireReadNML_interface(this, bounds, NLFilename )
!
! !DESCRIPTION:
! Read general fire namelist
!
! USES
+ use decompMod , only : bounds_type
import :: fire_method_type
! !ARGUMENTS:
class(fire_method_type) :: this
+ type(bounds_type), intent(in) :: bounds
character(len=*), intent(in) :: NLFilename
!-----------------------------------------------------------------------
@@ -97,6 +101,20 @@ subroutine FireInterp_interface(this, bounds)
end subroutine FireInterp_interface
+ !-----------------------------------------------------------------------
+ subroutine FireClean_interface(this)
+ !
+ ! !DESCRIPTION:
+ ! Deallocate Fire datasets
+ !
+ ! USES
+ import :: fire_method_type
+ ! !ARGUMENTS:
+ class(fire_method_type) :: this
+ !-----------------------------------------------------------------------
+
+ end subroutine FireClean_interface
+
!-----------------------------------------------------------------------
subroutine CNFireReadParams_interface( this, ncid )
!
diff --git a/src/main/histFileMod.F90 b/src/main/histFileMod.F90
index f5147559d9..23096722db 100644
--- a/src/main/histFileMod.F90
+++ b/src/main/histFileMod.F90
@@ -5099,9 +5099,9 @@ subroutine hist_restart_ncd (bounds, ncid, flag, rdate)
end if
call ncd_io(ncid=ncid_hist(t), flag='read', varname=trim(name), &
- dim1name=type1d_out, data=hbuf1d)
+ dim1name=type1d_out, data=hbuf1d, posNOTonfile=.true.)
call ncd_io(ncid=ncid_hist(t), flag='read', varname=trim(name_acc), &
- dim1name=type1d_out, data=nacs1d)
+ dim1name=type1d_out, data=nacs1d, posNOTonfile=.true.)
hbuf(beg1d_out:end1d_out,1) = hbuf1d(beg1d_out:end1d_out)
nacs(beg1d_out:end1d_out,1) = nacs1d(beg1d_out:end1d_out)
@@ -5110,9 +5110,9 @@ subroutine hist_restart_ncd (bounds, ncid, flag, rdate)
deallocate(nacs1d)
else
call ncd_io(ncid=ncid_hist(t), flag='read', varname=trim(name), &
- dim1name=type1d_out, data=hbuf)
+ dim1name=type1d_out, data=hbuf, posNOTonfile=.true.)
call ncd_io(ncid=ncid_hist(t), flag='read', varname=trim(name_acc), &
- dim1name=type1d_out, data=nacs)
+ dim1name=type1d_out, data=nacs, posNOTonfile=.true.)
end if
end do
diff --git a/src/main/ncdio_pio.F90.in b/src/main/ncdio_pio.F90.in
index 86f3e0cb43..991823fb67 100644
--- a/src/main/ncdio_pio.F90.in
+++ b/src/main/ncdio_pio.F90.in
@@ -541,14 +541,6 @@ contains
character(len=32) :: subname = 'ncd_inqfdims' ! subroutine name
!-----------------------------------------------------------------------
- if (single_column) then
- ni = 1
- nj = 1
- ns = 1
- isgrid2d = .true.
- RETURN
- end if
-
ni = 0
nj = 0
@@ -1353,7 +1345,7 @@ contains
start(:) = 0
count(:) = 0
- if (flag == 'read') then
+ if (flag == 'read' .or. flag == 'read_noscm') then
call ncd_inqvid(ncid, varname, varid, vardesc, readvar=varpresent)
@@ -1382,7 +1374,7 @@ contains
#else
if (varpresent) then
allocate(idata1d(size(data)))
- if (single_column) then
+ if (single_column .and. flag == 'read') then
call scam_field_offsets(ncid,'undefined', vardesc,&
start, count, found=found, posNOTonfile=posNOTonfile)
if ( found )then
@@ -1478,7 +1470,7 @@ contains
start(:) = 0
count(:) = 0
- if (flag == 'read') then
+ if (flag == 'read' .or. flag == 'read_noscm') then
call ncd_inqvid(ncid, varname, varid, vardesc, readvar=varpresent)
@@ -1499,7 +1491,7 @@ contains
end if
#else
if (varpresent) then
- if (single_column) then
+ if (single_column .and. flag == 'read') then
call scam_field_offsets(ncid,'undefined', vardesc,&
start, count, found=found, posNOTonfile=posNOTonfile)
if ( found )then
@@ -1648,7 +1640,7 @@ contains
!-----------------------------------------------------------------------
!TYPE int,double,logical
- subroutine ncd_io_1d_{TYPE}(varname, data, dim1name, flag, ncid, nt, readvar, cnvrtnan2fill)
+ subroutine ncd_io_1d_{TYPE}(varname, data, dim1name, flag, ncid, nt, readvar, cnvrtnan2fill, posNOTonfile)
!
! !DESCRIPTION:
! netcdf I/O for 1d
@@ -1662,6 +1654,7 @@ contains
integer , optional, intent(in) :: nt ! time sample index
logical , optional, intent(out) :: readvar ! true => variable is on initial dataset (read only)
logical , optional, intent(in) :: cnvrtnan2fill ! true => convert any NaN's to _FillValue (spval)
+ logical , optional, intent(in) :: posNOTonfile ! Position is NOT on this file
!
! Local Variables
character(len=8) :: subgrid_level_name ! nameg, namel, etc.
@@ -1676,12 +1669,15 @@ contains
integer :: start(3) ! netcdf start index
integer :: count(3) ! netcdf count index
integer :: status ! error code
+ logical :: found ! if true, found lat/lon dims on file
logical :: varpresent ! if true, variable is on tape
integer :: xtype ! type of var in file
integer , pointer :: idata(:) ! Temporary integer data to send to file
type(iodesc_plus_type) , pointer :: iodesc_plus
type(var_desc_t) :: vardesc
integer :: oldhandle ! previous value of pio_error_handle
+ integer :: ni,nj,ns ! lat/lon indicies
+ logical :: isgrid2d ! if true, latlon grid
character(len=*),parameter :: subname='ncd_io_1d_{TYPE}' ! subroutine name
!-----------------------------------------------------------------------
@@ -1703,14 +1699,15 @@ contains
end if
#endif
- if (flag == 'read') then
+ if (flag == 'read' .or. flag == 'read_noscm') then
call ncd_inqvid(ncid, varname, varid, vardesc, readvar=varpresent)
if (varpresent) then
if (single_column) then
start(:) = 1 ; count(:) = 1
- call scam_field_offsets(ncid,subgrid_level_name,vardesc,start,count)
- if (trim(subgrid_level_name) == grlnd) then
+ call scam_field_offsets(ncid,subgrid_level_name,vardesc,start,count,found=found,posNOTonfile=posNOTonfile)
+ call ncd_inqfdims(ncid, isgrid2d, ni, nj, ns)
+ if (isgrid2d) then
n=2
if (present(nt)) then
start(3) = nt ; count(3) = 1
@@ -1823,7 +1820,7 @@ contains
!TYPE int,double
subroutine ncd_io_2d_{TYPE}(varname, data, dim1name, lowerb2, upperb2, &
- flag, ncid, nt, readvar, switchdim, cnvrtnan2fill)
+ flag, ncid, nt, readvar, switchdim, cnvrtnan2fill, posNOTonfile )
!
! !DESCRIPTION:
! Netcdf i/o of 2d
@@ -1839,7 +1836,7 @@ contains
logical, optional, intent(out) :: readvar ! true => variable is on initial dataset (read only)
logical, optional, intent(in) :: switchdim ! true=> permute dim1 and dim2 for output
logical, optional, intent(in) :: cnvrtnan2fill ! true => convert any NaN's to _FillValue (spval)
- !
+ logical, optional, intent(in) :: posNOTonfile ! Position is NOT on this file !
! !LOCAL VARIABLES:
#if ({ITYPE}==TYPEINT)
integer , pointer :: temp(:,:)
@@ -1862,7 +1859,10 @@ contains
logical :: varpresent ! if true, variable is on tape
integer :: lb1,lb2
integer :: ub1,ub2
+ integer :: ni,nj,ns
+ logical :: isgrid2d ! if true, latlon grid
integer :: xtype ! netcdf type of variable on file
+ logical :: found ! if true, found lat/lon dims on file
type(iodesc_plus_type) , pointer :: iodesc_plus
type(var_desc_t) :: vardesc
@@ -1898,14 +1898,16 @@ contains
allocate(temp(lb2:ub2,lb1:ub1))
end if
- if (flag == 'read') then
+ if (flag == 'read' .or. flag == 'read_noscm') then
call ncd_inqvid(ncid, varname, varid, vardesc, readvar=varpresent)
if (varpresent) then
- if (single_column) then
+ if (single_column .and. flag == 'read') then
start(:) = 1 ; count(:) = 1
- call scam_field_offsets(ncid, subgrid_level_name, vardesc, start, count)
- if (trim(subgrid_level_name) == grlnd) then
+ call scam_field_offsets(ncid, subgrid_level_name, vardesc, start, count,found=found,posNOTonfile=posNOTonfile)
+ call ncd_inqfdims(ncid, isgrid2d, ni, nj, ns)
+ call ncd_inqvdims(ncid, ndims, vardesc)
+ if (isgrid2d) then
count(3) = size(data,dim=2)
n=3
if (present(nt)) then
@@ -1913,11 +1915,9 @@ contains
n=4
end if
else
- count(2) = size(data,dim=2)
- n=2
+ n=ndims
if (present(nt)) then
- start(3) = nt ; count(3) = 1
- n=3
+ start(n) = nt ; count(n) = 1
end if
end if
if (present(switchdim)) then
@@ -2067,7 +2067,7 @@ contains
!-----------------------------------------------------------------------
!TYPE int,double
- subroutine ncd_io_3d_{TYPE}(varname, data, dim1name, flag, ncid, nt, readvar)
+ subroutine ncd_io_3d_{TYPE}(varname, data, dim1name, flag, ncid, nt, readvar, posNOTonfile)
!
! !DESCRIPTION:
! Netcdf i/o of 3d
@@ -2080,7 +2080,7 @@ contains
character(len=*) , intent(in) :: dim1name ! dimension 1 name
integer, optional, intent(in) :: nt ! time sample index
logical, optional, intent(out) :: readvar ! true => variable is on initial dataset (read only)
- !
+ logical, optional, intent(in) :: posNOTonfile ! Position is NOT on this file !
! !LOCAL VARIABLES:
integer :: ndim1,ndim2
character(len=8) :: subgrid_level_name ! nameg, namel, etc.
@@ -2099,6 +2099,9 @@ contains
logical :: varpresent ! if true, variable is on tape
type(iodesc_plus_type) , pointer :: iodesc_plus
type(var_desc_t) :: vardesc
+ integer :: ni,nj,ns
+ logical :: isgrid2d ! if true, latlon grid
+ logical :: found ! if true, found lat/lon dims on file
character(len=*),parameter :: subname='ncd_io_3d_{TYPE}' ! subroutine name
!-----------------------------------------------------------------------
@@ -2108,15 +2111,16 @@ contains
write(iulog,*) trim(subname),' ',trim(flag),' ',trim(varname),' ',trim(subgrid_level_name)
end if
- if (flag == 'read') then
+ if (flag == 'read' .or. flag == 'read_noscm') then
call ncd_inqvid(ncid, varname, varid, vardesc, readvar=varpresent)
if (varpresent) then
- if (single_column) then
+ if (single_column .and. flag == 'read') then
start(:) = 1
count(:) = 1
- call scam_field_offsets(ncid, subgrid_level_name, vardesc, start, count)
- if (trim(subgrid_level_name) == grlnd) then
+ call scam_field_offsets(ncid, subgrid_level_name, vardesc, start, count,found=found,posNOTonfile=posNOTonfile)
+ call ncd_inqfdims(ncid, isgrid2d, ni, nj, ns)
+ if (isgrid2d) then
count(3) = size(data,dim=2);
count(4) = size(data,dim=3)
n=4
@@ -2435,7 +2439,10 @@ contains
if ( trim(dimname)=='nj'.or. trim(dimname)=='lat'.or. trim(dimname)=='lsmlat') then
start(i)=latidx
count(i)=1
- else if ( trim(dimname)=='ni'.or. trim(dimname)=='lon'.or. trim(dimname)=='lsmlon') then
+ else if ( trim(dimname)=='ni'.or. trim(dimname)=='lon'.or. trim(dimname)=='lsmlon'.or. trim(dimname)=='gridcell') then
+ start(i)=lonidx
+ count(i)=1
+ else if ( trim(dimname)=='gridcell') then
start(i)=lonidx
count(i)=1
else if ( trim(dimname)=='column') then
diff --git a/src/main/organicFileMod.F90 b/src/main/organicFileMod.F90
index 3adbd5b6f1..5b61a8c0db 100644
--- a/src/main/organicFileMod.F90
+++ b/src/main/organicFileMod.F90
@@ -6,8 +6,8 @@ module organicFileMod
! !MODULE: organicFileMod
!
! !DESCRIPTION:
-! Contains methods for reading in organic matter data file which has
-! organic matter density for each grid point and soil level
+! Contains methods for reading in organic matter data file which has
+! organic matter density for each grid point and soil level
!
! !USES
use abortutils , only : endrun
@@ -30,7 +30,7 @@ module organicFileMod
!
!EOP
!
-!-----------------------------------------------------------------------
+!-----------------------------------------------------------------------
contains
@@ -42,7 +42,7 @@ module organicFileMod
! !INTERFACE:
subroutine organicrd(organic)
!
-! !DESCRIPTION:
+! !DESCRIPTION:
! Read the organic matter dataset.
!
! !USES:
@@ -68,7 +68,7 @@ subroutine organicrd(organic)
!EOP
character(len=256) :: locfn ! local file name
type(file_desc_t) :: ncid ! netcdf id
- integer :: ni,nj,ns ! dimension sizes
+ integer :: ni,nj,ns ! dimension sizes
logical :: isgrid2d ! true => file is 2d
logical :: readvar ! true => variable is on dataset
character(len=32) :: subname = 'organicrd' ! subroutine name
@@ -77,9 +77,9 @@ subroutine organicrd(organic)
! Initialize data to zero - no organic matter dataset
organic(:,:) = 0._r8
-
+
! Read data if file was specified in namelist
-
+
if (fsurdat /= ' ') then
if (masterproc) then
write(iulog,*) 'Attempting to read organic matter data .....'
@@ -90,14 +90,14 @@ subroutine organicrd(organic)
call ncd_pio_openfile (ncid, locfn, 0)
call ncd_inqfdims (ncid, isgrid2d, ni, nj, ns)
- if (ldomain%ns /= ns .or. ldomain%ni /= ni .or. ldomain%nj /= nj) then
+ if (.not. single_column .and. (ldomain%ns /= ns .or. ldomain%ni /= ni .or. ldomain%nj /= nj)) then
write(iulog,*)trim(subname), 'ldomain and input file do not match dims '
write(iulog,*)trim(subname), 'ldomain%ni,ni,= ',ldomain%ni,ni
write(iulog,*)trim(subname), 'ldomain%nj,nj,= ',ldomain%nj,nj
write(iulog,*)trim(subname), 'ldomain%ns,ns,= ',ldomain%ns,ns
call endrun()
end if
-
+
call ncd_io(ncid=ncid, varname='ORGANIC', flag='read', data=organic, &
dim1name=grlnd, readvar=readvar)
if (.not. readvar) call endrun('organicrd: errror reading ORGANIC')
diff --git a/src/main/surfrdMod.F90 b/src/main/surfrdMod.F90
index 4005ec7845..c70ec28fa0 100644
--- a/src/main/surfrdMod.F90
+++ b/src/main/surfrdMod.F90
@@ -363,8 +363,10 @@ subroutine surfrd_get_num_patches (lfsurdat, actual_maxsoil_patches, actual_nump
type(file_desc_t) :: ncid ! netcdf file id
integer :: dimid ! netCDF dimension id
logical :: cft_dim_exists ! dimension exists on dataset
+ logical :: natpft_dim_exists ! dimension exists on dataset
integer :: check_numpft ! Surface dataset count of numpft, should
! match maxsoil_patches - actual_numcft
+ integer :: actual_numnatpft ! natpft value from sfc dataset
character(len=32) :: subname = 'surfrd_get_num_patches' ! subroutine name
!-----------------------------------------------------------------------
@@ -396,9 +398,17 @@ subroutine surfrd_get_num_patches (lfsurdat, actual_maxsoil_patches, actual_nump
call ncd_inqdlen(ncid, dimid, actual_maxsoil_patches, 'lsmpft')
actual_numpft = actual_maxsoil_patches - actual_numcft
- call ncd_inqdlen(ncid, dimid, check_numpft, 'natpft')
+ ! Read numpft
+ call ncd_inqdid(ncid, 'natpft', dimid, natpft_dim_exists)
+ if ( natpft_dim_exists ) then
+ call ncd_inqdlen(ncid, dimid, actual_numnatpft, 'natpft')
+ call ncd_inqdlen(ncid, dimid, check_numpft, 'natpft')
+ else
+ actual_numnatpft = 0
+ end if
- if(check_numpft.ne.actual_numpft)then
+!jt if(check_numpft.ne.actual_numpft)then
+ if(actual_numcft+actual_numnatpft.ne.actual_maxsoil_patches)then
write(iulog,*)'the sum of the cftdim and the natpft dim should match the lsmpft dim in the surface file'
write(iulog,*)'natpft: ',check_numpft
write(iulog,*)'lsmpft: ',actual_maxsoil_patches
diff --git a/src/soilbiogeochem/CMakeLists.txt b/src/soilbiogeochem/CMakeLists.txt
index e2baa2d1b2..ac467c3e5f 100644
--- a/src/soilbiogeochem/CMakeLists.txt
+++ b/src/soilbiogeochem/CMakeLists.txt
@@ -2,6 +2,7 @@
# source files that are currently used in unit tests
list(APPEND clm_sources
+ SoilBiogeochemCarbonFluxType.F90
SoilBiogeochemStateType.F90
SoilBiogeochemDecompCascadeConType.F90
SoilBiogeochemStateType.F90
diff --git a/src/unit_test_stubs/main/ncdio_pio_fake.F90.in b/src/unit_test_stubs/main/ncdio_pio_fake.F90.in
index e8ef14e457..7f38565e90 100644
--- a/src/unit_test_stubs/main/ncdio_pio_fake.F90.in
+++ b/src/unit_test_stubs/main/ncdio_pio_fake.F90.in
@@ -48,6 +48,7 @@ module ncdio_pio
public :: check_var ! determine if variable is on netcdf file
public :: check_dim ! determine if dimension is on netcdf file
public :: check_var_or_dim ! determine if variable or dimension is on netcdf file
+ public :: check_dim_size ! validity check on dimension
public :: ncd_io ! do fake i/o (currently only set up to read)
public :: ncd_inqvid ! inquire on a variable id
public :: ncd_set_var ! set data on "file" for one variable
@@ -340,6 +341,25 @@ contains
end subroutine check_var_or_dim
+ !-----------------------------------------------------------------------
+ subroutine check_dim_size(ncid, dimname, value, msg)
+ !
+ ! !DESCRIPTION:
+ ! Validity check on dimension
+ !
+ ! !ARGUMENTS:
+ class(file_desc_t),intent(in) :: ncid ! PIO file handle
+ character(len=*) , intent(in) :: dimname ! Dimension name
+ integer, intent(in) :: value ! Expected dimension size
+
+ character(len=*), intent(in), optional :: msg ! Optional additional message printed upon error
+ !
+ ! !LOCAL VARIABLES:
+ !-----------------------------------------------------------------------
+
+ ! Does nothing assumes the dim size is as expected
+
+ end subroutine check_dim_size
!-----------------------------------------------------------------------
subroutine ncd_inqdid(ncid, name, dimid, dimexist)
diff --git a/src/unit_test_stubs/share_esmf/CMakeLists.txt b/src/unit_test_stubs/share_esmf/CMakeLists.txt
index 1d767543ea..368601dcc8 100644
--- a/src/unit_test_stubs/share_esmf/CMakeLists.txt
+++ b/src/unit_test_stubs/share_esmf/CMakeLists.txt
@@ -1,5 +1,7 @@
list(APPEND clm_sources
ExcessIceStreamType.F90
+ FireDataBaseType.F90
+ laiStreamMod.F90
PrigentRoughnessStreamType.F90
ZenderSoilErodStreamType.F90
)
diff --git a/src/unit_test_stubs/share_esmf/FireDataBaseType.F90 b/src/unit_test_stubs/share_esmf/FireDataBaseType.F90
new file mode 100644
index 0000000000..63046188a3
--- /dev/null
+++ b/src/unit_test_stubs/share_esmf/FireDataBaseType.F90
@@ -0,0 +1,123 @@
+module FireDataBaseType
+
+#include "shr_assert.h"
+
+ !-----------------------------------------------------------------------
+ ! !DESCRIPTION:
+ ! module for handling of fire data
+ ! UNIT-TEST STUB for fire data Streams
+ ! This just allows the fire code to be tested without
+ ! reading in the streams data, by faking it and setting it to a
+ ! constant value.
+ !
+ ! !USES:
+ use shr_kind_mod , only : r8 => shr_kind_r8, CL => shr_kind_CL
+ use shr_log_mod , only : errMsg => shr_log_errMsg
+ use clm_varctl , only : iulog
+ use spmdMod , only : masterproc, mpicom, iam
+ use abortutils , only : endrun
+ use decompMod , only : bounds_type
+ use FireMethodType , only : fire_method_type
+ !
+ implicit none
+ private
+ !
+ ! !PUBLIC TYPES:
+ public :: fire_base_type
+ !
+ type, abstract, extends(fire_method_type) :: fire_base_type
+ private
+ ! !PRIVATE MEMBER DATA:
+ real(r8), public, pointer :: forc_hdm(:) ! Human population density
+ real(r8), public, pointer :: forc_lnfm(:) ! Lightning frequency
+ real(r8), public, pointer :: gdp_lf_col(:) ! col global real gdp data (k US$/capita)
+ real(r8), public, pointer :: peatf_lf_col(:) ! col global peatland fraction data (0-1)
+ integer , public, pointer :: abm_lf_col(:) ! col global peak month of crop fire emissions
+
+ contains
+ !
+ ! !PUBLIC MEMBER FUNCTIONS:
+ procedure, public :: BaseFireInit ! Initialization of Fire
+ procedure, public :: FireInit => BaseFireInit ! Initialization of Fire
+ procedure, public :: FireInterp ! Interpolate fire data
+ procedure, public :: BaseFireReadNML ! Read in the namelist
+ procedure, public :: FireReadNML => BaseFireReadNML ! Read in the namelist
+ procedure(need_lightning_and_popdens_interface), public, deferred :: &
+ need_lightning_and_popdens ! Returns true if need lightning & popdens
+
+ end type fire_base_type
+
+ abstract interface
+ !-----------------------------------------------------------------------
+ function need_lightning_and_popdens_interface(this) result(need_lightning_and_popdens)
+ !
+ ! !DESCRIPTION:
+ ! Returns true if need lightning and popdens, false otherwise
+ !
+ ! USES
+ import :: fire_base_type
+ !
+ ! !ARGUMENTS:
+ class(fire_base_type), intent(in) :: this
+ logical :: need_lightning_and_popdens ! function result
+ !-----------------------------------------------------------------------
+ end function need_lightning_and_popdens_interface
+ end interface
+
+ character(len=*), parameter, private :: sourcefile = &
+ __FILE__
+
+!==============================================================================
+contains
+!==============================================================================
+
+ subroutine BaseFireReadNML( this, bounds, NLFilename )
+ !
+ ! !DESCRIPTION:
+ ! Read the namelist for Fire
+ !
+ ! !USES:
+ !
+ ! !ARGUMENTS:
+ class(fire_base_type) :: this
+ type(bounds_type), intent(in) :: bounds
+ character(len=*), intent(in) :: NLFilename ! Namelist filename
+ end subroutine BaseFireReadNML
+
+ !================================================================
+ subroutine BaseFireInit( this, bounds )
+ !
+ ! !DESCRIPTION:
+ ! Initialize CN Fire module
+ ! !USES:
+ use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=)
+ !
+ ! !ARGUMENTS:
+ class(fire_base_type) :: this
+ type(bounds_type), intent(in) :: bounds
+ !-----------------------------------------------------------------------
+
+ if ( this%need_lightning_and_popdens() ) then
+
+ end if
+
+ end subroutine BaseFireInit
+
+ !================================================================
+ subroutine FireInterp(this,bounds)
+ !
+ ! !DESCRIPTION:
+ ! Interpolate CN Fire datasets
+ !
+ ! !ARGUMENTS:
+ class(fire_base_type) :: this
+ type(bounds_type), intent(in) :: bounds
+ !-----------------------------------------------------------------------
+
+ if ( this%need_lightning_and_popdens() ) then
+
+ end if
+
+ end subroutine FireInterp
+
+end module FireDataBaseType
diff --git a/src/unit_test_stubs/share_esmf/laiStreamMod.F90 b/src/unit_test_stubs/share_esmf/laiStreamMod.F90
new file mode 100644
index 0000000000..a39a3eb053
--- /dev/null
+++ b/src/unit_test_stubs/share_esmf/laiStreamMod.F90
@@ -0,0 +1,74 @@
+module laiStreamMod
+
+ !-----------------------------------------------------------------------
+ ! !DESCRIPTION:
+ ! Read LAI from stream
+ !
+ ! !USES:
+ use decompMod , only : bounds_type
+ use abortutils , only : endrun
+ use clm_varctl , only : iulog
+ !
+ ! !PUBLIC TYPES:
+ implicit none
+ private
+
+ ! !PUBLIC MEMBER FUNCTIONS:
+ public :: lai_init ! position datasets for LAI
+ public :: lai_advance ! Advance the LAI streams (outside of a Open-MP threading loop)
+ public :: lai_interp ! interpolates between two years of LAI data (when LAI streams
+
+ character(len=*), parameter :: sourcefile = &
+ __FILE__
+
+!==============================================================================
+contains
+!==============================================================================
+
+ subroutine lai_init(bounds)
+ !
+ ! Initialize data stream information for LAI.
+ !
+ ! !USES:
+ !
+ ! !ARGUMENTS:
+ type(bounds_type), intent(in) :: bounds ! bounds
+ !
+ ! !LOCAL VARIABLES:
+ !-----------------------------------------------------------------------
+
+ end subroutine lai_init
+
+ !================================================================
+ subroutine lai_advance( bounds )
+ !
+ ! Advance LAI streams
+ !
+ ! !USES:
+ !
+ ! !ARGUMENTS:
+ type(bounds_type), intent(in) :: bounds
+ !
+ ! !LOCAL VARIABLES:
+ !-----------------------------------------------------------------------
+
+ end subroutine lai_advance
+
+ !================================================================
+ subroutine lai_interp(bounds, canopystate_inst)
+ !
+ ! Interpolate data stream information for Lai.
+ !
+ ! !USES:
+ use CanopyStateType , only : canopystate_type
+ !
+ ! !ARGUMENTS:
+ type(bounds_type) , intent(in) :: bounds
+ type(canopystate_type) , intent(inout) :: canopystate_inst
+ !
+ ! !LOCAL VARIABLES:
+ !-----------------------------------------------------------------------
+
+ end subroutine lai_interp
+
+end module LaiStreamMod
diff --git a/src/utils/clmfates_interfaceMod.F90 b/src/utils/clmfates_interfaceMod.F90
index 2effb561dd..289244ae89 100644
--- a/src/utils/clmfates_interfaceMod.F90
+++ b/src/utils/clmfates_interfaceMod.F90
@@ -3231,7 +3231,8 @@ subroutine Init2(this, bounds, NLFilename)
call t_startf('fates_init2')
- call this%fates_fire_data_method%FireInit(bounds, NLFilename)
+ call this%fates_fire_data_method%FireInit(bounds)
+ call this%fates_fire_data_method%FireReadNML(bounds, NLFilename)
call t_stopf('fates_init2')