diff --git a/cime_config/tests.py b/cime_config/tests.py
index 37af54e8c88f..6bbb8581ce24 100644
--- a/cime_config/tests.py
+++ b/cime_config/tests.py
@@ -436,21 +436,30 @@
},
#fates testmod coverage
+ "fates_landuse" : {
+ "time" : "00:40:00",
+ "tests" : (
+ "ERS_Ld60.f45_g37.IELMFATES.elm-fates_cold_logging",
+ "ERS_D_Ld30.f45_g37.IELMFATES.elm-fates_cold_landuse",
+ "ERS_D_Ld30.f45_g37.IELMFATES.elm-fates_cold_luh2",
+ "ERS_D_Ld30.f45_g37.IELMFATES.elm-fates_cold_luh2harvestarea",
+ "ERS_D_Ld30.f45_g37.IELMFATES.elm-fates_cold_luh2harvestmass",
+ )
+ },
+ #fates testmod coverage
"fates" : {
- "inherit" : ("fates_long_tests", "fates_elm_developer"),
+ "inherit" : ("fates_long_tests", "fates_elm_developer", "fates_landuse"),
"tests" : (
"ERP_Ld15.ne4pg2_ne4pg2.IELMFATES.elm-fates_cold_allvars",
"ERP_Ld3.f09_g16.IELMFATES.elm-fates_cold",
"ERP_D_Ld3.f19_g16.IELMFATES.elm-fates_cold",
"ERS_D_Ld3_PS.f09_g16.IELMFATES.elm-fates_cold",
"ERS_D_Ld5.f45_g37.IELMFATES.elm-fates_cold",
- "ERS_D_Ld30.f45_g37.IELMFATES.elm-fates_cold_landuse",
"ERS_Ld30.f45_g37.IELMFATES.elm-fates_satphen",
"ERS_Ld30.f45_g37.IELMFATES.elm-fates_cold_fixedbiogeo",
"ERS_Ld30.f45_g37.IELMFATES.elm-fates_cold_nocomp",
"ERS_Ld30.f45_g37.IELMFATES.elm-fates_cold_nocomp_fixedbiogeo",
"ERS_Ld60.f45_g37.IELMFATES.elm-fates",
- "ERS_Ld60.f45_g37.IELMFATES.elm-fates_cold_logging",
"ERS_Ld60.f45_g37.IELMFATES.elm-fates_cold_nofire",
"ERS_Ld60.f45_g37.IELMFATES.elm-fates_cold_st3",
"ERS_Ld60.f45_g37.IELMFATES.elm-fates_cold_pphys",
diff --git a/components/elm/bld/ELMBuildNamelist.pm b/components/elm/bld/ELMBuildNamelist.pm
index 67347728e0fd..68afd92e132d 100755
--- a/components/elm/bld/ELMBuildNamelist.pm
+++ b/components/elm/bld/ELMBuildNamelist.pm
@@ -808,12 +808,29 @@ sub setup_cmdl_fates_mode {
# The following variables may be set by the user and are compatible with use_fates
# no need to set defaults, covered in a different routine
- my @list = ( "fates_spitfire_mode", "use_vertsoilc", "use_century_decomp", "fates_seeddisp_cadence",
- "use_fates_planthydro", "use_fates_ed_st3", "use_fates_ed_prescribed_phys",
- "use_fates_inventory_init", "use_fates_fixed_biogeog", "use_fates_nocomp","use_fates_sp",
- "fates_inventory_ctrl_filename","use_fates_logging", "use_fates_tree_damage",
- "use_fates_parteh_mode","use_fates_cohort_age_tracking","use_snicar_ad", "use_fates_luh",
- "fluh_timeseries","fates_history_dimlevel");
+ my @list = ( "flandusepftdat",
+ "fluh_timeseries",
+ "fates_harvest_mode",
+ "fates_history_dimlevel",
+ "fates_inventory_ctrl_filename",
+ "fates_parteh_mode",
+ "fates_seeddisp_cadence",
+ "fates_spitfire_mode",
+ "use_fates_cohort_age_tracking",
+ "use_fates_ed_st3",
+ "use_fates_ed_prescribed_phys",
+ "use_fates_fixed_biogeog",
+ "use_fates_inventory_init",
+ "use_fates_luh",
+ "use_fates_lupft",
+ "use_fates_nocomp",
+ "use_fates_planthydro",
+ "use_fates_potentialveg",
+ "use_fates_sp",
+ "use_fates_tree_damage",
+ "use_century_decomp",
+ "use_snicar_ad",
+ "use_vertsoilc");
foreach my $var ( @list ) {
if ( defined($nl->get_value($var)) ) {
$nl_flags->{$var} = $nl->get_value($var);
@@ -841,17 +858,17 @@ sub setup_cmdl_fates_mode {
if ( defined($nl->get_value($var)) ) {
fatal_error("$var is being set, but can ONLY be set when -bgc fates option is used.\n");
}
- $var = "use_fates_cohort_age_tracking";
+ $var = "fates_harvest_mode";
if ( defined($nl->get_value($var)) ) {
fatal_error("$var is being set, but can ONLY be set when -bgc fates option is used.\n");
}
- $var = "use_fates_fixed_biogeog";
+ $var = "use_fates_cohort_age_tracking";
if ( defined($nl->get_value($var)) ) {
fatal_error("$var is being set, but can ONLY be set when -bgc fates option is used.\n");
}
- $var = "use_fates_logging";
+ $var = "use_fates_fixed_biogeog";
if ( defined($nl->get_value($var)) ) {
- fatal_error("$var is being set, but can ONLY be set when -bgc fates option is used.\n");
+ fatal_error("$var is being set, but can ONLY be set when -bgc fates option is used.\n");
}
$var = "fates_parteh_mode";
if ( defined($nl->get_value($var)) ) {
@@ -877,6 +894,14 @@ sub setup_cmdl_fates_mode {
if ( defined($nl->get_value($var)) ) {
fatal_error("$var is being set, but can ONLY be set when -bgc fates option is used.\n");
}
+ $var = "use_fates_lupft";
+ if ( defined($nl->get_value($var)) ) {
+ fatal_error("$var is being set, but can ONLY be set when -bgc fates option is used.\n");
+ }
+ $var = "use_fates_potentialveg";
+ if ( defined($nl->get_value($var)) ) {
+ fatal_error("$var is being set, but can ONLY be set when -bgc fates option is used.\n");
+ }
$var = "fates_inventory_ctrl_filename";
if ( defined($nl->get_value($var)) ) {
fatal_error("$var is being set, but can ONLY be set when -bgc fates option is used.\n");
@@ -2812,8 +2837,8 @@ sub setup_logic_do_harvest {
if (string_is_undef_or_empty($nl->get_value('flanduse_timeseries'))) {
$cannot_be_true = "$var can only be set to true when running a transient case (flanduse_timeseries non-blank)";
}
- elsif (!( value_is_true($nl->get_value('use_cn')) || value_is_true($nl->get_value('use_fates')) )) {
- $cannot_be_true = "$var can only be set to true when running with CN (use_cn == true) or when using FATES (use_fates == true)";
+ elsif (!( value_is_true($nl->get_value('use_cn')))) {
+ $cannot_be_true = "$var can only be set to true when running with CN (use_cn == true)";
}
if ($cannot_be_true) {
@@ -3380,25 +3405,42 @@ sub setup_logic_fates {
my ($test_files, $nl_flags, $definition, $defaults, $nl, $physv) = @_;
if ( value_is_true( $nl_flags->{'use_fates'}) ) {
- add_default($test_files, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'fates_spitfire_mode', 'use_fates'=>$nl_flags->{'use_fates'} );
- add_default($test_files, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_fates_fixed_biogeog', 'use_fates'=>$nl_flags->{'use_fates'} );
- add_default($test_files, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_fates_logging', 'use_fates'=>$nl_flags->{'use_fates'});
- add_default($test_files, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_fates_planthydro', 'use_fates'=>$nl_flags->{'use_fates'});
- add_default($test_files, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'fates_parteh_mode', 'use_fates'=>$nl_flags->{'use_fates'});
- add_default($test_files, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_fates_ed_st3', 'use_fates'=>$nl_flags->{'use_fates'});
- add_default($test_files, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_fates_ed_prescribed_phys', 'use_fates'=>$nl_flags->{'use_fates'});
- add_default($test_files, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_fates_inventory_init', 'use_fates'=>$nl_flags->{'use_fates'});
- add_default($test_files, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'fates_inventory_ctrl_filename','use_fates'=>$nl_flags->{'use_fates'});
- add_default($test_files, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_fates_cohort_age_tracking','use_fates'=>$nl_flags->{'use_fates'});
- add_default($test_files, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_fates_sp', 'use_fates'=>$nl_flags->{'use_fates'});
- add_default($test_files, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_fates_nocomp', 'use_fates'=>$nl_flags->{'use_fates'});
- add_default($test_files, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_fates_tree_damage', 'use_fates'=>$nl_flags->{'use_fates'});
- add_default($test_files, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'fates_seeddisp_cadence', 'use_fates'=>$nl_flags->{'use_fates'});
- add_default($test_files, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_fates_luh', 'use_fates'=>$nl_flags->{'use_fates'});
+
add_default($test_files, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'fates_paramfile', 'phys'=>$nl_flags->{'phys'});
- add_default($test_files, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'fluh_timeseries', 'phys'=>$nl_flags->{'phys'});
- add_default($test_files, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'fates_history_dimlevel','use_fates'=>$nl_flags->{'use_fates'});
-
+
+ # add other fates modes whose defaults don't depend on other modes
+ my @list = ( "fates_harvest_mode",
+ "fates_history_dimlevel",
+ "fates_inventory_ctrl_filename",
+ "fates_parteh_mode",
+ "fates_seeddisp_cadence",
+ "fates_spitfire_mode",
+ "use_fates_cohort_age_tracking",
+ "use_fates_ed_st3",
+ "use_fates_ed_prescribed_phys",
+ "use_fates_inventory_init",
+ "use_fates_lupft",
+ "use_fates_planthydro",
+ "use_fates_potentialveg",
+ "use_fates_sp",
+ "use_fates_tree_damage");
+
+ foreach my $var (@list) {
+ add_default($test_files, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var,'use_fates'=>$nl_flags->{'use_fates'});
+ }
+
+ # Add defaults for fates modes that depend on previously set fates modes. See namelist defaults file for list.
+ add_default($test_files, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_fates_luh', 'use_fates'=>$nl_flags->{'use_fates'},
+ 'use_fates_lupft'=>$nl->get_value('use_fates_lupft'),
+ 'use_fates_potentialveg'=>$nl->get_value('use_fates_potentialveg'),
+ 'fates_harvest_mode'=>remove_leading_and_trailing_quotes($nl->get_value('fates_harvest_mode')) );
+ add_default($test_files, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_fates_nocomp', 'use_fates'=>$nl_flags->{'use_fates'},
+ 'use_fates_lupft'=>$nl->get_value('use_fates_lupft'),
+ 'use_fates_sp'=>$nl->get_value('use_fates_sp') );
+ add_default($test_files, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_fates_fixed_biogeog', 'use_fates'=>$nl_flags->{'use_fates'},
+ 'use_fates_lupft'=>$nl->get_value('use_fates_lupft'),
+ 'use_fates_sp'=>$nl->get_value('use_fates_sp') );
+
# For FATES SP mode make sure no-competion, 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";
@@ -3418,21 +3460,104 @@ sub setup_logic_fates {
if (&value_is_true( $nl->get_value('use_fates_planthydro') )) {
fatal_error('fates sp mode is currently not supported to work with fates hydro');
}
+ # FATES landuse can not be active with fates sp mode is active
+ if ( &value_is_true($nl->get_value('use_fates_luh')) ) {
+ fatal_error("use_fates_luh is can NOT be true when use_fates_sp is true" );
+ }
+ }
+ }
+ # make sure that fates landuse x pft mode has the necessary run mode configurations
+ # and add the necessary landuse x pft static mapping data default if not defined
+ my $var = "use_fates_lupft";
+ if ( defined($nl->get_value($var)) ) {
+ if ( &value_is_true($nl->get_value($var)) ) {
+ my @list = ( "use_fates_luh", "use_fates_nocomp", "use_fates_fixed_biogeog" );
+ foreach my $var ( @list ) {
+ if ( ! &value_is_true($nl->get_value($var)) ) {
+ fatal_error("$var is required when use_fates_lupft is true" );
+ }
+ }
}
}
# check that fates landuse change mode has the necessary luh2 landuse timeseries data
+ # and add the default if not defined
my $var = "use_fates_luh";
if ( defined($nl->get_value($var)) ) {
if ( &value_is_true($nl->get_value($var)) ) {
- $var = "fluh_timeseries";
- add_default($test_files, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var,
- 'phys'=>$nl_flags->{'phys'}, 'hgrid'=>$nl_flags->{'res'},
- 'sim_year_range'=>$nl_flags->{'sim_year_range'}, nofail=>1 );
+ $var = "use_fates_potentialveg";
+ if ( defined($nl->get_value($var)) ) {
+ if ( ! &value_is_true($nl->get_value($var)) ) {
+ $var = "fluh_timeseries";
+ add_default($test_files, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var,
+ 'use_fates'=>$nl_flags->{'use_fates'}, 'hgrid'=>$nl_flags->{'res'},
+ 'sim_year_range'=>$nl_flags->{'sim_year_range'} );
+ my $fname = remove_leading_and_trailing_quotes( $nl->get_value($var) );
+ if ( ! defined($nl->get_value($var)) ) {
+ fatal_error("$var is required when use_fates_luh is set" );
+ } elsif ( ! -f "$fname" ) {
+ fatal_error("$var does NOT point to a valid filename" );
+ }
+ }
+ }
+ $var = "use_fates_fixed_biogeog";
+ if ( defined($nl->get_value($var)) ) {
+ if ( &value_is_true($nl->get_value($var)) ) {
+ $var = "flandusepftdat";
+ add_default($test_files, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, 'use_fates'=>$nl_flags->{'use_fates'},
+ 'phys'=>$nl_flags->{'phys'}, 'hgrid'=>$nl_flags->{'res'}, nofail=>1 );
+ my $fname = remove_leading_and_trailing_quotes( $nl->get_value($var) );
+ if ( ! defined($nl->get_value($var)) ) {
+ fatal_error("$var is required when use_fates_luh and use_fates_fixed_biogeog is set" );
+ } elsif ( ! -f "$fname" ) {
+ fatal_error("$var does NOT point to a valid filename" );
+ }
+ }
+ }
+ }
+ }
+
+ # check that fates landuse is on and harvest mode is off when potential veg switch is true
+ my $var = "use_fates_potentialveg";
+ if ( defined($nl->get_value($var)) ) {
+ if ( &value_is_true($nl->get_value($var)) ) {
+ if ( ! &value_is_true($nl->get_value('use_fates_luh')) ) {
+ fatal_error("use_fates_luh must be true when $var is true" );
+ }
+ my $var = remove_leading_and_trailing_quotes($nl->get_value('fates_harvest_mode'));
+ if ( $var ne 'no_harvest') {
+ fatal_error("fates_harvest_mode set to $var. It must set to no_harvest when use_fates_potential_veg is true." );
+ }
+ # it is ok for fluh_timeseries to be defined as long as the string is empty
+ my $var = "fluh_timeseries";
+ if ( defined($nl->get_value($var)) ) {
+ if (! string_is_undef_or_empty($nl->get_value($var))) {
+ fatal_error("fluh_timeseries can not be set when use_fates_potentialveg is true" );
+ }
+ }
+ }
+ }
+
+ # Check fates_harvest_mode compatibility
+ my $var = "fates_harvest_mode";
+ if ( defined($nl->get_value($var)) ) {
+ # using fates_harvest mode with raw luh2 harvest data
+ my $mode = remove_leading_and_trailing_quotes($nl->get_value($var));
+ if ( $mode eq "luhdata_area" || $mode eq "luhdata_mass" ) {
+ # Make sure that use_fates_luh is true when using raw fates luh2 harvest data
+ if ( ! &value_is_true($nl->get_value('use_fates_luh')) ) {
+ fatal_error("use_fates_luh is required to be true when $var is luhdata_mass or luhdata_area" );
+ }
+ } elsif ( $mode eq 'landuse_timeseries' ) {
+ # Check to make sure that the user set the flanduse_timeseries file
+ # Since the flanduse_timeseries logic checking is upstream of the fates logic,
+ # don't add the default here. The onus is on the user to match the correct timeseries
+ # data to the correct surface dataset resolution
+ my $var = "flanduse_timeseries";
my $fname = remove_leading_and_trailing_quotes( $nl->get_value($var) );
if ( ! defined($nl->get_value($var)) ) {
- fatal_error("$var is required when use_fates_luh is set" );
+ fatal_error("$var is required when fates_harvest_mode is landuse_timeseries" );
} elsif ( ! -f "$fname" ) {
- fatal_error("$fname does NOT point to a valid filename" );
+ fatal_error("$var does NOT point to a valid filename" );
}
}
}
diff --git a/components/elm/bld/namelist_files/namelist_defaults.xml b/components/elm/bld/namelist_files/namelist_defaults.xml
index 2fe8b19aaa87..316292219861 100644
--- a/components/elm/bld/namelist_files/namelist_defaults.xml
+++ b/components/elm/bld/namelist_files/namelist_defaults.xml
@@ -134,7 +134,7 @@ attributes from the config_cache.xml file (with keys converted to upper-case).
-lnd/clm2/paramdata/fates_params_api.35.0.0_12pft_c240326.nc
+lnd/clm2/paramdata/fates_params_api.36.0.0_12pft_c240517.nc
lnd/clm2/paramdata/CNP_parameters_c131108.nc
@@ -587,10 +587,15 @@ lnd/clm2/surfdata_map/surfdata_conusx4v1_simyr2000_c160503.nc
lnd/clm2/surfdata_map/surfdata.pftdyn_ne30np4_rcp2.6_simyr1850-2100_c130524.nc
-
+
lnd/clm2/surfdata_map/fates-sci.1.68.3_api.31.0.0_tools.1.0.1/LUH2_states_transitions_management.timeseries_4x5_hist_simyr1850-2015_c231101.nc
+lnd/clm2/surfdata_map/fates-sci.1.68.3_api.31.0.0_tools.1.0.1/LUH2_states_transitions_management.timeseries_4x5_hist_simyr1850-2015_c231101.nc
+
+
+lnd/clm2/surfdata_map/fates-sci.1.77.0_api.36.0.0/fates_landuse_pft_map_4x5_240206.nc
@@ -2177,25 +2182,31 @@ this mask will have smb calculated over the entire global land surface
0
-.false.
-.false.
+no_harvest
+2,2
+ "/dev/null"
+1
+0
.false.
.false.
.false.
.false.
-.false.
.false.
.false.
-.false.
-1
-0
+.false.
+.false.
+.true.
+.true.
+.true.
+.true.
+.false.
.false.
- "/dev/null"
.true.
+.true.
.false.
.true.
+.true.
.false.
-2,2
.true.
.true.
.false.
diff --git a/components/elm/bld/namelist_files/namelist_definition.xml b/components/elm/bld/namelist_files/namelist_definition.xml
index 16bca299ddd7..74e1967fc529 100644
--- a/components/elm/bld/namelist_files/namelist_definition.xml
+++ b/components/elm/bld/namelist_files/namelist_definition.xml
@@ -308,6 +308,20 @@ Allowed values are:
5 : use gross domestic production and population datasets to simulate anthropogenic fire supression
+
+Set FATES harvesting mode by setting fates_harvest_mode
+Allowed values are:
+ no_harvest : no fates harvesting of any kind
+ event_code : fates logging via fates logging event codes only (via fates parameter file)
+ landuse_timeseries: fates harvest driven by HLM landuse timeseries data (dynHarvestMod)
+ luhdata_area : fates harvest driven by LUH2 raw harvest data, area-based (dynFATESLandUseChangeMod)
+ luhdata_mass : fates harvest driven by LUH2 raw harvest data, mass-based (dynFATESLandUseChangeMod)
+Note that the landuse_timeseries option is not the same as the FATES fluh_timeseries data file.
+This option is older than the luhdata options and may be depricated at some point in the future.
+
+
Switch deciding which nutrient model to use in FATES.
@@ -339,11 +353,6 @@ Toggle to turn on FATES no competition mode (only relevant if FATES is being use
Toggle to turn on FATES satellite phenology mode (only relevant if FATES is being used).
-
-Toggle to turn on the logging module (only relevant if FATES is being used).
-
-
Toggle to turn on plant hydraulics (only relevant if FATES is on).
@@ -382,12 +391,29 @@ Full pathname to the inventory initialization control file.
+ group="elm_inparm" valid_values="" value=".false.">
If TRUE, enable use of land use state and transition data from luh_timeseries file.
-(Only valid for fates land use change runs, where there is a luh_timeseries file.)
+This is enabled by default if fates_harvest_mode is set to use the raw LUH2 harvest data
(Also, only valid for use_fates = true and is incompatible with transient runs currently.)
+
+If TRUE, enable use of fates land use x pft mapping data file. This mode
+requires the use of the land use x pft association static data map file. See the
+flandusepftdat definition entry in this file for more information.
+(Only valid for use_fates = true and is incompatible with transient runs currently.)
+
+
+
+If TRUE, ignore the land-use state vector and transitions, and assert that all lands
+are primary, and that there is no harvest. This mode is only relevant for FATES
+spin-up workflows that are intending to use the spin-up restart output to start a
+FATES land use transient case using the use_fates_lupft namelist option. The option
+should be set to true for the spin-up case and false for the transient case.
+
+
@@ -408,6 +434,18 @@ output level is not enabled.
(Only relevant if FATES is on)
+
+Full pathname of fates landuse x pft data map.
+The file associates land use types with pfts across a static global map.
+This file is necessary for running FATES with use_fates_luh,
+use_fates_nocomp, and use_fates_fixedbiogeo engaged (note that use_fates_lupft
+is provided as a namelist option to engage all necessary options). The file is output
+by the FATES land use data tool (https://github.com/NGEET/tools-fates-landusedata)
+which processes the raw land use data from the THEMIS tool data sets
+(https://doi.org/10.5065/29s7-7b41)
+
+
Toggle to turn on if Kennedy et al plant hydraulics model is used.
diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates/user_nl_elm b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates/user_nl_elm
index cd078b90950c..575517b98fd2 100644
--- a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates/user_nl_elm
+++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates/user_nl_elm
@@ -16,7 +16,7 @@ hist_fincl1 = 'FATES_NCOHORTS', 'FATES_TRIMMING', 'FATES_AREA_PLANTS',
'FATES_SAPWOODC', 'FATES_LEAFC', 'FATES_FROOTC', 'FATES_REPROC',
'FATES_STRUCTC', 'FATES_NONSTRUCTC', 'FATES_VEGC_ABOVEGROUND',
'FATES_CANOPY_VEGC', 'FATES_USTORY_VEGC', 'FATES_PRIMARY_PATCHFUSION_ERR',
-'FATES_HARVEST_CARBON_FLUX', 'FATES_DISTURBANCE_RATE_FIRE',
+'FATES_HARVEST_WOODPROD_C_FLUX', 'FATES_DISTURBANCE_RATE_FIRE',
'FATES_DISTURBANCE_RATE_LOGGING', 'FATES_DISTURBANCE_RATE_TREEFALL',
'FATES_STOMATAL_COND', 'FATES_LBLAYER_COND', 'FATES_NPP', 'FATES_GPP',
'FATES_AUTORESP', 'FATES_GROWTH_RESP', 'FATES_MAINT_RESP', 'FATES_GPP_CANOPY',
diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_landuse/user_nl_elm b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_landuse/user_nl_elm
index 098d4fd33a38..94067cfefeba 100644
--- a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_landuse/user_nl_elm
+++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_landuse/user_nl_elm
@@ -1,2 +1,2 @@
flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_map/landuse.timeseries_4x5_hist_simyr1850-2015_200311.nc'
-do_harvest = .true.
+fates_harvest_mode = 'landuse_timeseries'
diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_logging/user_nl_elm b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_logging/user_nl_elm
index 3b74a4fd3798..d2079d9e4386 100644
--- a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_logging/user_nl_elm
+++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_logging/user_nl_elm
@@ -1 +1 @@
-use_fates_logging= .true.
+fates_harvest_mode = 'event_code'
diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_luh2/README b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_luh2/README
new file mode 100644
index 000000000000..79d6511d1728
--- /dev/null
+++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_luh2/README
@@ -0,0 +1,2 @@
+Currently the FATES LUH2 category of test mods currently only supports
+4x5 grid resolutions.
diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_luh2/user_nl_elm b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_luh2/user_nl_elm
index 854c21407f1a..3f089bcf49d2 100644
--- a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_luh2/user_nl_elm
+++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_luh2/user_nl_elm
@@ -1 +1,5 @@
use_fates_luh = .true.
+use_fates_nocomp = .true.
+use_fates_fixed_biogeog = .true.
+use_fates_sp = .false.
+use_fates_potentialveg = .false.
diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_luh2harvestarea/include_user_mods b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_luh2harvestarea/include_user_mods
new file mode 100644
index 000000000000..9474118e0370
--- /dev/null
+++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_luh2harvestarea/include_user_mods
@@ -0,0 +1 @@
+../fates_cold_luh2
diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_luh2harvestarea/user_nl_elm b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_luh2harvestarea/user_nl_elm
new file mode 100644
index 000000000000..426b41b49e59
--- /dev/null
+++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_luh2harvestarea/user_nl_elm
@@ -0,0 +1 @@
+fates_harvest_mode = 'luhdata_area'
diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_luh2harvestmass/include_user_mods b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_luh2harvestmass/include_user_mods
new file mode 100644
index 000000000000..9474118e0370
--- /dev/null
+++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_luh2harvestmass/include_user_mods
@@ -0,0 +1 @@
+../fates_cold_luh2
diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_luh2harvestmass/user_nl_elm b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_luh2harvestmass/user_nl_elm
new file mode 100644
index 000000000000..7b6bc24f5a79
--- /dev/null
+++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_luh2harvestmass/user_nl_elm
@@ -0,0 +1 @@
+fates_harvest_mode = 'luhdata_mass'
diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_eca/user_nl_elm b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_eca/user_nl_elm
index 8dfdff1ab8eb..bd31fbbc4b68 100644
--- a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_eca/user_nl_elm
+++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_eca/user_nl_elm
@@ -21,7 +21,7 @@ hist_fincl1 = 'FATES_NCOHORTS', 'FATES_TRIMMING', 'FATES_AREA_PLANTS',
'FATES_SAPWOODC', 'FATES_LEAFC', 'FATES_FROOTC', 'FATES_REPROC',
'FATES_STRUCTC', 'FATES_NONSTRUCTC', 'FATES_VEGC_ABOVEGROUND',
'FATES_CANOPY_VEGC', 'FATES_USTORY_VEGC', 'FATES_PRIMARY_PATCHFUSION_ERR',
-'FATES_HARVEST_CARBON_FLUX', 'FATES_DISTURBANCE_RATE_FIRE',
+'FATES_HARVEST_WOODPROD_C_FLUX', 'FATES_DISTURBANCE_RATE_FIRE',
'FATES_DISTURBANCE_RATE_LOGGING', 'FATES_DISTURBANCE_RATE_TREEFALL',
'FATES_STOMATAL_COND', 'FATES_LBLAYER_COND', 'FATES_NPP', 'FATES_GPP',
'FATES_AUTORESP', 'FATES_GROWTH_RESP', 'FATES_MAINT_RESP', 'FATES_GPP_CANOPY',
diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_long/user_nl_elm b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_long/user_nl_elm
index 4812969a278b..e8e22f163b05 100644
--- a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_long/user_nl_elm
+++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_long/user_nl_elm
@@ -16,7 +16,7 @@ hist_fincl1 = 'FATES_NCOHORTS', 'FATES_TRIMMING', 'FATES_AREA_PLANTS',
'FATES_SAPWOODC', 'FATES_LEAFC', 'FATES_FROOTC', 'FATES_REPROC',
'FATES_STRUCTC', 'FATES_NONSTRUCTC', 'FATES_VEGC_ABOVEGROUND',
'FATES_CANOPY_VEGC', 'FATES_USTORY_VEGC', 'FATES_PRIMARY_PATCHFUSION_ERR',
-'FATES_HARVEST_CARBON_FLUX', 'FATES_DISTURBANCE_RATE_FIRE',
+'FATES_HARVEST_WOODPROD_C_FLUX', 'FATES_DISTURBANCE_RATE_FIRE',
'FATES_DISTURBANCE_RATE_LOGGING', 'FATES_DISTURBANCE_RATE_TREEFALL',
'FATES_STOMATAL_COND', 'FATES_LBLAYER_COND', 'FATES_NPP', 'FATES_GPP',
'FATES_AUTORESP', 'FATES_GROWTH_RESP', 'FATES_MAINT_RESP', 'FATES_GPP_CANOPY',
diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_rd/user_nl_elm b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_rd/user_nl_elm
index 1e72d72d5712..263e4b5fad7c 100644
--- a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_rd/user_nl_elm
+++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_rd/user_nl_elm
@@ -21,7 +21,7 @@ hist_fincl1 = 'FATES_NCOHORTS', 'FATES_TRIMMING', 'FATES_AREA_PLANTS',
'FATES_SAPWOODC', 'FATES_LEAFC', 'FATES_FROOTC', 'FATES_REPROC',
'FATES_STRUCTC', 'FATES_NONSTRUCTC', 'FATES_VEGC_ABOVEGROUND',
'FATES_CANOPY_VEGC', 'FATES_USTORY_VEGC', 'FATES_PRIMARY_PATCHFUSION_ERR',
-'FATES_HARVEST_CARBON_FLUX', 'FATES_DISTURBANCE_RATE_FIRE',
+'FATES_HARVEST_WOODPROD_C_FLUX', 'FATES_DISTURBANCE_RATE_FIRE',
'FATES_DISTURBANCE_RATE_LOGGING', 'FATES_DISTURBANCE_RATE_TREEFALL',
'FATES_STOMATAL_COND', 'FATES_LBLAYER_COND', 'FATES_NPP', 'FATES_GPP',
'FATES_AUTORESP', 'FATES_GROWTH_RESP', 'FATES_MAINT_RESP', 'FATES_GPP_CANOPY',
diff --git a/components/elm/src/dyn_subgrid/dynFATESLandUseChangeMod.F90 b/components/elm/src/dyn_subgrid/dynFATESLandUseChangeMod.F90
index 53be7987182e..04f76767f546 100644
--- a/components/elm/src/dyn_subgrid/dynFATESLandUseChangeMod.F90
+++ b/components/elm/src/dyn_subgrid/dynFATESLandUseChangeMod.F90
@@ -9,6 +9,7 @@ module dynFATESLandUseChangeMod
! !USES:
use shr_kind_mod , only : r8 => shr_kind_r8
use shr_log_mod , only : errMsg => shr_log_errMsg
+ use spmdMod , only : masterproc
use decompMod , only : bounds_type, BOUNDS_LEVEL_PROC
use abortutils , only : endrun
use dynFileMod , only : dyn_file_type
@@ -22,12 +23,36 @@ module dynFATESLandUseChangeMod
real(r8), allocatable, public :: landuse_transitions(:,:)
real(r8), allocatable, public :: landuse_states(:,:)
+ real(r8), allocatable, public :: landuse_harvest(:,:)
integer, public, parameter :: num_landuse_transition_vars = 108
integer, public, parameter :: num_landuse_state_vars = 12
+ integer, public, parameter :: num_landuse_harvest_vars = 5
+
+ ! Define the fates landuse namelist mode switch values
+ character(len=18), public, parameter :: fates_harvest_no_logging = 'no_harvest'
+ character(len=18), public, parameter :: fates_harvest_logging_only = 'event_code'
+ character(len=18), public, parameter :: fates_harvest_hlmlanduse = 'landuse_timeseries'
+ character(len=18), public, parameter :: fates_harvest_luh_area = 'luhdata_area'
+ character(len=18), public, parameter :: fates_harvest_luh_mass = 'luhdata_mass'
+
+ ! Define landuse harvest unit integer representation
+ integer, public, parameter :: landuse_harvest_area_units = 1
+ integer, public, parameter :: landuse_harvest_mass_units = 2
+ integer, public :: landuse_harvest_units
type(dyn_file_type), target :: dynFatesLandUse_file
+ ! LUH2 raw wood harvest area fraction
+ character(len=10), target :: landuse_harvest_area_varnames(num_landuse_harvest_vars) = &
+ [character(len=10) :: 'primf_harv', 'primn_harv', 'secmf_harv', 'secyf_harv', 'secnf_harv']
+
+ ! LUH2 raw wood harvest biomass carbon
+ character(len=10), target :: landuse_harvest_mass_varnames(num_landuse_harvest_vars) = &
+ [character(len=10) :: 'primf_bioh', 'primn_bioh', 'secmf_bioh', 'secyf_bioh', 'secnf_bioh']
+
+ character(len=10), public, pointer :: landuse_harvest_varnames(:) => null()
+
! Land use name arrays
character(len=5), public, parameter :: landuse_state_varnames(num_landuse_state_vars) = &
[character(len=5) :: 'primf', & ! forested primary land
@@ -69,8 +94,9 @@ module dynFATESLandUseChangeMod
'c3nfx_to_c3ann','c3nfx_to_c4ann','c3nfx_to_c3per','c3nfx_to_c4per', &
'c3nfx_to_secdf','c3nfx_to_secdn','c3nfx_to_pastr','c3nfx_to_range','c3nfx_to_urban']
- type(dyn_var_time_uninterp_type) :: landuse_transition_vars(num_landuse_transition_vars) ! value of each landuse variable
- type(dyn_var_time_uninterp_type) :: landuse_state_vars(num_landuse_state_vars) ! value of each landuse variable
+ type(dyn_var_time_uninterp_type) :: landuse_transition_vars(num_landuse_transition_vars) ! value of each transitions variable
+ type(dyn_var_time_uninterp_type) :: landuse_state_vars(num_landuse_state_vars) ! value of each state variable
+ type(dyn_var_time_uninterp_type) :: landuse_harvest_vars(num_landuse_harvest_vars) ! value of each harvest variable
public :: dynFatesLandUseInit
public :: dynFatesLandUseInterp
@@ -84,14 +110,15 @@ subroutine dynFatesLandUseInit(bounds, landuse_filename)
! Initialize data structures for land use information.
! !USES:
- use elm_varctl , only : use_fates_luh
+ use elm_varctl , only : use_fates_luh, fates_harvest_mode
+ use elm_varctl , only : use_fates_potentialveg
use dynVarTimeUninterpMod , only : dyn_var_time_uninterp_type
use dynTimeInfoMod , only : YEAR_POSITION_START_OF_TIMESTEP
use dynTimeInfoMod , only : YEAR_POSITION_END_OF_TIMESTEP
! !ARGUMENTS:
- type(bounds_type), intent(in) :: bounds ! proc-level bounds
- character(len=*) , intent(in) :: landuse_filename ! name of file containing land use information
+ type(bounds_type), intent(in) :: bounds ! proc-level bounds
+ character(len=*) , intent(in) :: landuse_filename ! name of file containing landuse timeseries information (fates luh2)
! !LOCAL VARIABLES
integer :: varnum, i ! counter for harvest variables
@@ -114,37 +141,71 @@ subroutine dynFatesLandUseInit(bounds, landuse_filename)
if (ier /= 0) then
call endrun(msg=' allocation error for landuse_transitions'//errMsg(__FILE__, __LINE__))
end if
+ allocate(landuse_harvest(num_landuse_harvest_vars,bounds%begg:bounds%endg),stat=ier)
+ if (ier /= 0) then
+ call endrun(msg=' allocation error for landuse_harvest'//errMsg(__FILE__, __LINE__))
+ end if
+ ! Initialize the states, transitions and harvest mapping percentages as zero by defaut
landuse_states = 0._r8
landuse_transitions = 0._r8
+ landuse_harvest = 0._r8
+
+ ! Avoid initializing the landuse timeseries file if in fates potential vegetation mode
+ if (.not. use_fates_potentialveg) then
+ if (use_fates_luh) then
+
+ ! Generate the dyn_file_type object
+ ! Start calls get_prev_date, whereas end calls get_curr_date
+ dynFatesLandUse_file = dyn_file_type(landuse_filename, YEAR_POSITION_END_OF_TIMESTEP)
+
+ ! Get initial land use data from the fates luh2 timeseries dataset
+ num_points = (bounds%endg - bounds%begg + 1)
+ landuse_shape(1) = num_points ! Does this need an explicit array shape to be passed to the constructor?
+ do varnum = 1, num_landuse_transition_vars
+ landuse_transition_vars(varnum) = dyn_var_time_uninterp_type( &
+ dyn_file=dynFatesLandUse_file, varname=landuse_transition_varnames(varnum), &
+ dim1name=grlnd, conversion_factor=1.0_r8, &
+ do_check_sums_equal_1=.false., data_shape=landuse_shape)
+ end do
+ do varnum = 1, num_landuse_state_vars
+ landuse_state_vars(varnum) = dyn_var_time_uninterp_type( &
+ dyn_file=dynFatesLandUse_file, varname=landuse_state_varnames(varnum), &
+ dim1name=grlnd, conversion_factor=1.0_r8, &
+ do_check_sums_equal_1=.false., data_shape=landuse_shape)
+ end do
+
+ ! Get the harvest rate data from the fates luh2 timeseries dataset if enabled
+ if (trim(fates_harvest_mode) .eq. fates_harvest_luh_area .or. &
+ trim(fates_harvest_mode) .eq. fates_harvest_luh_mass) then
+
+ ! change the harvest varnames being used depending on the mode selected
+ if (trim(fates_harvest_mode) .eq. fates_harvest_luh_area ) then
+ landuse_harvest_varnames => landuse_harvest_area_varnames
+ landuse_harvest_units = landuse_harvest_area_units
+ elseif (trim(fates_harvest_mode) .eq. fates_harvest_luh_mass ) then
+ landuse_harvest_varnames => landuse_harvest_mass_varnames
+ landuse_harvest_units = landuse_harvest_mass_units
+ else
+ call endrun(msg=' undefined fates harvest mode selected'//errMsg(__FILE__, __LINE__))
+ end if
+
+ do varnum = 1, num_landuse_harvest_vars
+ landuse_harvest_vars(varnum) = dyn_var_time_uninterp_type( &
+ dyn_file=dynFatesLandUse_file, varname=landuse_harvest_varnames(varnum), &
+ dim1name=grlnd, conversion_factor=1.0_r8, &
+ do_check_sums_equal_1=.false., data_shape=landuse_shape)
+ end do
+ end if
+
+ end if
+
+ ! Since fates needs state data during initialization, make sure to call
+ ! the interpolation routine at the start
+ call dynFatesLandUseInterp(bounds,init_state=.true.)
- if (use_fates_luh) then
-
- ! Generate the dyn_file_type object. Note that the land use data being read in is for the
- ! transitions occuring within the current year
- dynFatesLandUse_file = dyn_file_type(landuse_filename, YEAR_POSITION_END_OF_TIMESTEP)
-
- ! Get initial land use data
- num_points = (bounds%endg - bounds%begg + 1)
- landuse_shape(1) = num_points ! Does this need an explicit array shape to be passed to the constructor?
- do varnum = 1, num_landuse_transition_vars
- landuse_transition_vars(varnum) = dyn_var_time_uninterp_type( &
- dyn_file=dynFatesLandUse_file, varname=landuse_transition_varnames(varnum), &
- dim1name=grlnd, conversion_factor=1.0_r8, &
- do_check_sums_equal_1=.false., data_shape=landuse_shape)
- end do
- do varnum = 1, num_landuse_state_vars
- landuse_state_vars(varnum) = dyn_var_time_uninterp_type( &
- dyn_file=dynFatesLandUse_file, varname=landuse_state_varnames(varnum), &
- dim1name=grlnd, conversion_factor=1.0_r8, &
- do_check_sums_equal_1=.false., data_shape=landuse_shape)
- end do
end if
- ! Since fates needs state data during initialization, make sure to call
- ! the interpolation routine at the start
- call dynFatesLandUseInterp(bounds,init_state=.true.)
-
end subroutine dynFatesLandUseInit
@@ -152,6 +213,7 @@ end subroutine dynFatesLandUseInit
subroutine dynFatesLandUseInterp(bounds, init_state)
use dynTimeInfoMod , only : time_info_type
+ use elm_varctl , only : fates_harvest_mode
! !ARGUMENTS:
type(bounds_type), intent(in) :: bounds ! proc-level bounds
@@ -171,13 +233,14 @@ subroutine dynFatesLandUseInterp(bounds, init_state)
init_flag = init_state
end if
- ! input land use data for current year are stored in year+1 in the file
- call dynFatesLandUse_file%time_info%set_current_year_get_year(1)
+ ! Get the data for the current year
+ call dynFatesLandUse_file%time_info%set_current_year_get_year()
if (dynFatesLandUse_file%time_info%is_before_time_series() .and. .not.(init_flag)) then
! Reset the land use transitions to zero for safety
landuse_transitions(1:num_landuse_transition_vars,bounds%begg:bounds%endg) = 0._r8
landuse_states(1:num_landuse_state_vars,bounds%begg:bounds%endg) = 0._r8
+ landuse_harvest(1:num_landuse_harvest_vars,bounds%begg:bounds%endg) = 0._r8
else
! Right now we don't account for the topounits
allocate(this_data(bounds%begg:bounds%endg))
@@ -189,9 +252,17 @@ subroutine dynFatesLandUseInterp(bounds, init_state)
call landuse_state_vars(varnum)%get_current_data(this_data)
landuse_states(varnum,bounds%begg:bounds%endg) = this_data(bounds%begg:bounds%endg)
end do
+ if (trim(fates_harvest_mode) .eq. fates_harvest_luh_area .or. &
+ trim(fates_harvest_mode) .eq. fates_harvest_luh_mass) then
+ do varnum = 1, num_landuse_harvest_vars
+ call landuse_harvest_vars(varnum)%get_current_data(this_data)
+ landuse_harvest(varnum,bounds%begg:bounds%endg) = this_data(bounds%begg:bounds%endg)
+ end do
+ end if
deallocate(this_data)
end if
end subroutine dynFatesLandUseInterp
+
end module dynFATESLandUseChangeMod
diff --git a/components/elm/src/dyn_subgrid/dynHarvestMod.F90 b/components/elm/src/dyn_subgrid/dynHarvestMod.F90
index b30643e9757d..5256f415efe2 100644
--- a/components/elm/src/dyn_subgrid/dynHarvestMod.F90
+++ b/components/elm/src/dyn_subgrid/dynHarvestMod.F90
@@ -188,6 +188,9 @@ subroutine dynHarvest_interp_harvest_types(bounds)
end do
deallocate(this_data)
end if
+
+ ! FATES does not make use of the get_do_harvest mechanism. Make sure this is always false for fates runs.
+ if (use_fates) do_harvest = .false.
end if
end subroutine dynHarvest_interp_harvest_types
diff --git a/components/elm/src/dyn_subgrid/dynSubgridDriverMod.F90 b/components/elm/src/dyn_subgrid/dynSubgridDriverMod.F90
index 8ac0cf4c45e7..7335d47fb099 100644
--- a/components/elm/src/dyn_subgrid/dynSubgridDriverMod.F90
+++ b/components/elm/src/dyn_subgrid/dynSubgridDriverMod.F90
@@ -71,11 +71,13 @@ subroutine dynSubgrid_init(bounds, glc2lnd_vars, crop_vars)
! clumps - so this routine needs to be called from outside any loops over clumps.
!
! !USES:
- use decompMod , only : bounds_type, BOUNDS_LEVEL_PROC
- use decompMod , only : get_proc_clumps, get_clump_bounds
- use dynpftFileMod , only : dynpft_init
- use dynHarvestMod , only : dynHarvest_init
- use dynpftFileMod , only : dynpft_interp
+ use decompMod , only : bounds_type, BOUNDS_LEVEL_PROC
+ use decompMod , only : get_proc_clumps, get_clump_bounds
+ use dynpftFileMod , only : dynpft_init
+ use dynHarvestMod , only : dynHarvest_init
+ use dynpftFileMod , only : dynpft_interp
+ use elm_varctl , only : fates_harvest_mode
+ use dynFATESLandUseChangeMod , only : fates_harvest_hlmlanduse
!
! !ARGUMENTS:
type(bounds_type) , intent(in) :: bounds ! processor-level bounds
@@ -103,7 +105,7 @@ subroutine dynSubgrid_init(bounds, glc2lnd_vars, crop_vars)
end if
! Initialize stuff for harvest (currently shares the flanduse_timeseries file)
- if (get_do_harvest()) then
+ if (get_do_harvest() .or. fates_harvest_mode == fates_harvest_hlmlanduse) then
call dynHarvest_init(bounds, harvest_filename=get_flanduse_timeseries())
end if
@@ -154,7 +156,8 @@ subroutine dynSubgrid_driver(bounds_proc, &
!
! !USES:
use elm_varctl , only : use_cn, create_glacier_mec_landunit
- use elm_varctl , only : use_fates, use_fates_luh
+ use elm_varctl , only : use_fates, use_fates_luh, fates_harvest_mode
+ use elm_varctl , only : use_fates_potentialveg
use decompMod , only : bounds_type, get_proc_clumps, get_clump_bounds
use decompMod , only : BOUNDS_LEVEL_PROC
use dynInitColumnsMod , only : initialize_new_columns
@@ -164,6 +167,7 @@ subroutine dynSubgrid_driver(bounds_proc, &
use dynHarvestMod , only : dynHarvest_interp_harvest_types
use dynFATESLandUseChangeMod, only : dynFatesLandUseInterp
+ use dynFATESLandUseChangeMod , only : fates_harvest_hlmlanduse
use dynEDMod , only : dyn_ED
use reweightMod , only : reweight_wrapup
@@ -244,11 +248,11 @@ subroutine dynSubgrid_driver(bounds_proc, &
call dyncrop_interp(bounds_proc,crop_vars)
end if
- if (get_do_harvest()) then
+ if (get_do_harvest() .or. fates_harvest_mode == fates_harvest_hlmlanduse) then
call dynHarvest_interp_harvest_types(bounds_proc)
end if
- if (use_fates_luh) then
+ if (use_fates_luh .and. .not. use_fates_potentialveg) then
call dynFatesLandUseInterp(bounds_proc)
end if
diff --git a/components/elm/src/external_models/fates b/components/elm/src/external_models/fates
index b8e4eee5ed46..1982b0032c3c 160000
--- a/components/elm/src/external_models/fates
+++ b/components/elm/src/external_models/fates
@@ -1 +1 @@
-Subproject commit b8e4eee5ed46daf5c9e710e9ebbe6d20464adbc8
+Subproject commit 1982b0032c3cab6278892eccb85f643114ffb1af
diff --git a/components/elm/src/main/controlMod.F90 b/components/elm/src/main/controlMod.F90
index 02c3ccf0867f..24bb855ff61a 100755
--- a/components/elm/src/main/controlMod.F90
+++ b/components/elm/src/main/controlMod.F90
@@ -250,7 +250,7 @@ subroutine control_init( )
namelist /elm_inparm / use_c13, use_c14
namelist /elm_inparm/ fates_paramfile, use_fates, &
- fates_spitfire_mode, use_fates_logging, &
+ fates_spitfire_mode, fates_harvest_mode, &
use_fates_planthydro, use_fates_ed_st3, &
use_fates_cohort_age_tracking, &
use_fates_ed_prescribed_phys, &
@@ -260,7 +260,10 @@ subroutine control_init( )
use_fates_nocomp, &
use_fates_sp, &
use_fates_luh, &
+ use_fates_lupft, &
+ use_fates_potentialveg, &
fluh_timeseries, &
+ flandusepftdat, &
fates_parteh_mode, &
fates_seeddisp_cadence, &
use_fates_tree_damage, &
@@ -804,9 +807,10 @@ subroutine control_spmd()
call mpi_bcast (fates_spitfire_mode, 1, MPI_INTEGER, 0, mpicom, ier)
+ call mpi_bcast (fates_harvest_mode, len(fates_harvest_mode), MPI_CHARACTER, 0, mpicom, ier)
call mpi_bcast (fates_paramfile, len(fates_paramfile) , MPI_CHARACTER, 0, mpicom, ier)
call mpi_bcast (fluh_timeseries, len(fluh_timeseries) , MPI_CHARACTER, 0, mpicom, ier)
- call mpi_bcast (use_fates_logging, 1, MPI_LOGICAL, 0, mpicom, ier)
+ call mpi_bcast (flandusepftdat, len(flandusepftdat) , MPI_CHARACTER, 0, mpicom, ier)
call mpi_bcast (use_fates_planthydro, 1, MPI_LOGICAL, 0, mpicom, ier)
call mpi_bcast (use_fates_cohort_age_tracking, 1, MPI_LOGICAL, 0, mpicom, ier)
call mpi_bcast (use_fates_ed_st3, 1, MPI_LOGICAL, 0, mpicom, ier)
@@ -814,6 +818,8 @@ subroutine control_spmd()
call mpi_bcast (use_fates_nocomp, 1, MPI_LOGICAL, 0, mpicom, ier)
call mpi_bcast (use_fates_sp, 1, MPI_LOGICAL, 0, mpicom, ier)
call mpi_bcast (use_fates_luh, 1, MPI_LOGICAL, 0, mpicom, ier)
+ call mpi_bcast (use_fates_lupft, 1, MPI_LOGICAL, 0, mpicom, ier)
+ call mpi_bcast (use_fates_potentialveg, 1, MPI_LOGICAL, 0, mpicom, ier)
call mpi_bcast (use_fates_ed_prescribed_phys, 1, MPI_LOGICAL, 0, mpicom, ier)
call mpi_bcast (use_fates_inventory_init, 1, MPI_LOGICAL, 0, mpicom, ier)
call mpi_bcast (fates_inventory_ctrl_filename, len(fates_inventory_ctrl_filename), &
@@ -1220,9 +1226,10 @@ subroutine control_print ()
write(iulog, *) ' use_fates = ', use_fates
if (use_fates) then
write(iulog, *) ' fates_spitfire_mode = ', fates_spitfire_mode
- write(iulog, *) ' use_fates_logging = ', use_fates_logging
+ write(iulog, *) ' fates_harvest_mode = ', fates_harvest_mode
write(iulog, *) ' fates_paramfile = ', fates_paramfile
- write(iulog, *) ' fluh_timeseries = ', fluh_timeseries
+ write(iulog, *) ' fluh_timeseries = ', trim(fluh_timeseries)
+ write(iulog, *) ' flandusepftdat = ', trim(flandusepftdat)
write(iulog, *) ' use_fates_planthydro = ', use_fates_planthydro
write(iulog, *) ' use_fates_tree_damage = ', use_fates_tree_damage
write(iulog, *) ' use_fates_cohort_age_tracking = ',use_fates_cohort_age_tracking
@@ -1234,6 +1241,8 @@ subroutine control_print ()
write(iulog, *) ' use_fates_nocomp = ', use_fates_nocomp
write(iulog, *) ' use_fates_sp = ', use_fates_sp
write(iulog, *) ' use_fates_luh = ', use_fates_luh
+ write(iulog, *) ' use_fates_lupft = ', use_fates_lupft
+ write(iulog, *) ' use_fates_potentialveg = ', use_fates_potentialveg
write(iulog, *) ' fates_inventory_ctrl_filename = ',fates_inventory_ctrl_filename
write(iulog, *) ' fates_seeddisp_cadence = ', fates_seeddisp_cadence
write(iulog, *) ' fates_seeddisp_cadence: 0, 1, 2, 3 => off, daily, monthly, or yearly dispersal'
diff --git a/components/elm/src/main/elm_instMod.F90 b/components/elm/src/main/elm_instMod.F90
index 90b576c320d6..ca74dda6ccf4 100644
--- a/components/elm/src/main/elm_instMod.F90
+++ b/components/elm/src/main/elm_instMod.F90
@@ -145,6 +145,8 @@ subroutine elm_inst_biogeochem(bounds_proc)
! initialize biogeochemical variables
use elm_varcon , only : c13ratio, c14ratio
use histFileMod , only : hist_printflds
+ use elm_varctl , only : flandusepftdat
+
implicit none
type(bounds_type), intent(in) :: bounds_proc
@@ -245,7 +247,7 @@ subroutine elm_inst_biogeochem(bounds_proc)
! Initialize the Functionaly Assembled Terrestrial Ecosystem Simulator (FATES)
if (use_fates) then
- call alm_fates%init(bounds_proc)
+ call alm_fates%init(bounds_proc, flandusepftdat)
end if
call hist_printflds()
diff --git a/components/elm/src/main/elm_varctl.F90 b/components/elm/src/main/elm_varctl.F90
index b9ddd4b24397..46b0d3c65a41 100644
--- a/components/elm/src/main/elm_varctl.F90
+++ b/components/elm/src/main/elm_varctl.F90
@@ -221,8 +221,8 @@ module elm_varctl
logical, public :: use_fates = .false. ! true => use ED
integer, public :: fates_spitfire_mode = 0 ! 0 for no fire; 1 for constant ignitions
+ character(len=13), public :: fates_harvest_mode = '' ! five different harvest modes; see namelist_definitions
logical, public :: use_fates_fixed_biogeog = .false. ! true => use fixed biogeography mode
- logical, public :: use_fates_logging = .false. ! true => turn on logging module
logical, public :: use_fates_planthydro = .false. ! true => turn on fates hydro
logical, public :: use_fates_cohort_age_tracking = .false. ! true => turn on cohort age tracking
logical, public :: use_fates_tree_damage = .false. ! true => turn on tree damage module
@@ -232,7 +232,10 @@ module elm_varctl
logical, public :: use_fates_nocomp = .false. ! true => no competition mode
logical, public :: use_fates_sp = .false. ! true => FATES satellite phenology mode
logical, public :: use_fates_luh = .false. ! true => FATES land use transitions mode
+ logical, public :: use_fates_lupft = .false. ! true => FATES land use x pft mode
+ logical, public :: use_fates_potentialveg = .false. ! true => FATES potential veg only
character(len=256), public :: fluh_timeseries = '' ! filename for land use harmonization data
+ character(len=256), public :: flandusepftdat = '' ! filename for fates landuse x pft data
character(len=256), public :: fates_inventory_ctrl_filename = '' ! filename for inventory control
integer, public :: fates_parteh_mode = -9 ! 1 => carbon only
! 2 => C+N+P (not enabled yet)
diff --git a/components/elm/src/main/elmfates_interfaceMod.F90 b/components/elm/src/main/elmfates_interfaceMod.F90
index 1b9d6c1ba490..a20444d67582 100644
--- a/components/elm/src/main/elmfates_interfaceMod.F90
+++ b/components/elm/src/main/elmfates_interfaceMod.F90
@@ -44,18 +44,21 @@ module ELMFatesInterfaceMod
use elm_varctl , only : use_fates
use elm_varctl , only : use_vertsoilc
use elm_varctl , only : fates_spitfire_mode
+ use elm_varctl , only : fates_harvest_mode
use elm_varctl , only : fates_parteh_mode
use elm_varctl , only : fates_seeddisp_cadence
use elm_varctl , only : use_fates_planthydro
use elm_varctl , only : use_fates_cohort_age_tracking
use elm_varctl , only : use_fates_ed_st3
use elm_varctl , only : use_fates_ed_prescribed_phys
- use elm_varctl , only : use_fates_logging
use elm_varctl , only : use_fates_inventory_init
use elm_varctl , only : use_fates_fixed_biogeog
use elm_varctl , only : use_fates_nocomp
use elm_varctl , only : use_fates_sp
use elm_varctl , only : use_fates_luh
+ use elm_varctl , only : use_fates_lupft
+ use elm_varctl , only : use_fates_potentialveg
+ use elm_varctl , only : flandusepftdat
use elm_varctl , only : use_fates_tree_damage
use elm_varctl , only : nsrest, nsrBranch
use elm_varctl , only : fates_inventory_ctrl_filename
@@ -172,14 +175,23 @@ module ELMFatesInterfaceMod
use dynHarvestMod , only : num_harvest_vars, harvest_varnames, wood_harvest_units
use dynHarvestMod , only : harvest_rates ! these are dynamic in space and time
- use dynSubgridControlMod , only : get_do_harvest ! this gets the namelist value
use FatesConstantsMod , only : hlm_harvest_area_fraction
use FatesConstantsMod , only : hlm_harvest_carbon
- use dynFATESLandUseChangeMod, only : num_landuse_transition_vars, num_landuse_state_vars
- use dynFATESLandUseChangeMod, only : landuse_transitions, landuse_states
- use dynFATESLandUseChangeMod, only : landuse_transition_varnames, landuse_state_varnames
- use dynFATESLandUseChangeMod, only : dynFatesLandUseInterp
+ use dynFATESLandUseChangeMod, only : num_landuse_transition_vars
+ use dynFATESLandUseChangeMod, only : num_landuse_state_vars
+ use dynFATESLandUseChangeMod, only : num_landuse_harvest_vars
+ use dynFATESLandUseChangeMod, only : landuse_transitions
+ use dynFATESLandUseChangeMod, only : landuse_states
+ use dynFATESLandUseChangeMod, only : landuse_harvest
+ use dynFATESLandUseChangeMod, only : landuse_transition_varnames
+ use dynFATESLandUseChangeMod, only : landuse_state_varnames
+ use dynFATESLandUseChangeMod, only : landuse_harvest_varnames
+ use dynFATESLandUseChangeMod, only : landuse_harvest_units
+ use dynFATESLandUseChangeMod, only : fates_harvest_no_logging
+ use dynFATESLandUseChangeMod, only : fates_harvest_hlmlanduse
+ use dynFATESLandUseChangeMod, only : fates_harvest_luh_area
+ use dynFATESLandUseChangeMod, only : fates_harvest_luh_mass
use FatesInterfaceTypesMod , only : bc_in_type, bc_out_type
@@ -282,6 +294,8 @@ module ELMFatesInterfaceMod
character(len=*), parameter, private :: sourcefile = &
__FILE__
+ integer, parameter :: num_landuse_pft_vars = 4
+
public :: ELMFatesGlobals1
public :: ELMFatesGlobals2
public :: ELMFatesTimesteps
@@ -388,12 +402,14 @@ subroutine ELMFatesGlobals2()
integer :: pass_inventory_init
integer :: pass_is_restart
integer :: pass_cohort_age_tracking
- integer :: pass_num_lu_harvest_types
+ integer :: pass_num_lu_harvest_cats
integer :: pass_lu_harvest
integer :: pass_tree_damage
integer :: pass_use_luh
+ integer :: pass_use_potentialveg
integer :: pass_num_luh_states
integer :: pass_num_luh_transitions
+ integer :: pass_lupftdat
! ----------------------------------------------------------------------------------
! FATES lightning definitions
! 1 : use a global constant lightning rate found in fates_params.
@@ -439,7 +455,7 @@ subroutine ELMFatesGlobals2()
end if
call set_fates_ctrlparms('use_tree_damage',ival=pass_tree_damage)
- if((trim(nu_com).eq.'ECA') .or. (trim(nu_com).eq.'MIC')) then
+ if((trim(nu_com)=='ECA') .or. (trim(nu_com)=='MIC')) then
call set_fates_ctrlparms('nu_com',cval='ECA')
else
call set_fates_ctrlparms('nu_com',cval='RD')
@@ -463,7 +479,7 @@ subroutine ELMFatesGlobals2()
call set_fates_ctrlparms('nitrogen_spec',ival=1)
call set_fates_ctrlparms('phosphorus_spec',ival=1)
- if(is_restart() .or. nsrest .eq. nsrBranch) then
+ if(is_restart() .or. nsrest == nsrBranch) then
pass_is_restart = 1
else
pass_is_restart = 0
@@ -506,26 +522,30 @@ subroutine ELMFatesGlobals2()
call set_fates_ctrlparms('sf_successful_ignitions_def',ival=successful_ignitions)
call set_fates_ctrlparms('sf_anthro_ignitions_def',ival=anthro_ignitions)
- ! check fates logging namelist value first because hlm harvest overrides it
- if(use_fates_logging) then
- pass_logging = 1
- else
- pass_logging = 0
+ ! FATES logging and harvest modes
+ pass_logging = 0
+ pass_lu_harvest = 0
+ pass_num_lu_harvest_cats = 0
+ if (trim(fates_harvest_mode) /= fates_harvest_no_logging) then
+ pass_logging = 1 ! Time driven logging, without landuse harvest
+ ! CLM landuse timeseries driven harvest rates
+ if (trim(fates_harvest_mode) == fates_harvest_hlmlanduse) then
+ pass_num_lu_harvest_cats = num_harvest_vars
+ pass_lu_harvest = 1
+
+ ! LUH2 landuse timeseries driven harvest rates
+ else if (trim(fates_harvest_mode) == fates_harvest_luh_area .or. &
+ trim(fates_harvest_mode) == fates_harvest_luh_mass) then
+ pass_lu_harvest = 1
+ pass_num_lu_harvest_cats = num_landuse_harvest_vars
+ end if
end if
- if(get_do_harvest()) then
- pass_logging = 1
- pass_num_lu_harvest_types = num_harvest_vars
- pass_lu_harvest = 1
- else
- pass_lu_harvest = 0
- pass_num_lu_harvest_types = 0
- end if
call set_fates_ctrlparms('use_lu_harvest',ival=pass_lu_harvest)
- call set_fates_ctrlparms('num_lu_harvest_cats',ival=pass_num_lu_harvest_types)
+ call set_fates_ctrlparms('num_lu_harvest_cats',ival=pass_num_lu_harvest_cats)
call set_fates_ctrlparms('use_logging',ival=pass_logging)
- if (use_fates_luh) then
+ if(use_fates_luh) then
pass_use_luh = 1
pass_num_luh_states = num_landuse_state_vars
pass_num_luh_transitions = num_landuse_transition_vars
@@ -534,10 +554,18 @@ subroutine ELMFatesGlobals2()
pass_num_luh_states = 0
pass_num_luh_transitions = 0
end if
+
call set_fates_ctrlparms('use_luh2',ival=pass_use_luh)
call set_fates_ctrlparms('num_luh2_states',ival=pass_num_luh_states)
call set_fates_ctrlparms('num_luh2_transitions',ival=pass_num_luh_transitions)
+ if ( use_fates_potentialveg ) then
+ pass_use_potentialveg = 1
+ else
+ pass_use_potentialveg = 0
+ end if
+ call set_fates_ctrlparms('use_fates_potentialveg',ival=pass_use_potentialveg)
+
if(use_fates_ed_st3) then
pass_ed_st3 = 1
else
@@ -689,7 +717,7 @@ end subroutine ELMFatesTimesteps
! ====================================================================================
- subroutine init(this, bounds_proc )
+ subroutine init(this, bounds_proc, flandusepftdat)
! ---------------------------------------------------------------------------------
! This initializes the hlm_fates_interface_type
@@ -721,6 +749,7 @@ subroutine init(this, bounds_proc )
! Input Arguments
class(hlm_fates_interface_type), intent(inout) :: this
type(bounds_type),intent(in) :: bounds_proc
+ character(len=*), intent(in) :: flandusepftdat
! local variables
integer :: nclumps ! Number of threads
@@ -739,6 +768,9 @@ subroutine init(this, bounds_proc )
integer :: ndecomp
integer :: numg
+ real(r8), allocatable :: landuse_pft_map(:,:,:)
+ real(r8), allocatable :: landuse_bareground(:)
+
! Initialize the FATES communicators with the HLM
! This involves to stages
! 1) allocate the vectors
@@ -764,6 +796,13 @@ subroutine init(this, bounds_proc )
write(iulog,*) 'alm_fates%init(): allocating for ',nclumps,' threads'
end if
+ ! Retrieve the landuse x pft static data if the optional switch has been set
+ if (use_fates_fixed_biogeog .and. use_fates_luh) then
+ call GetLandusePFTData(bounds_proc, flandusepftdat, landuse_pft_map, landuse_bareground)
+ end if
+
+ nclumps = get_proc_clumps()
+
!$OMP PARALLEL DO PRIVATE (nc,bounds_clump,nmaxcol,s,c,l,g,collist,pi,pf,ft)
do nc = 1,nclumps
@@ -882,17 +921,25 @@ subroutine init(this, bounds_proc )
endif
endif
- ! initialize static layers for reduced complexity FATES versions from HLM
- this%fates(nc)%bc_in(s)%pft_areafrac(:)=0._r8
- do m = surfpft_lb,surfpft_ub
- ft = m-surfpft_lb
- this%fates(nc)%bc_in(s)%pft_areafrac(ft)=wt_nat_patch(g,t,m)
- end do
+ if (use_fates_fixed_biogeog) then
+ ! Transfer the landuse x pft data to fates via bc_in if landuse mode engaged
+ if (use_fates_luh) then
+ this%fates(nc)%bc_in(s)%pft_areafrac_lu(:,1:num_landuse_pft_vars) = landuse_pft_map(g,:,1:num_landuse_pft_vars)
+ this%fates(nc)%bc_in(s)%baregroundfrac = landuse_bareground(g)
+ else
+ ! initialize static layers for reduced complexity FATES versions from HLM
+ this%fates(nc)%bc_in(s)%pft_areafrac(:)=0._r8
+ do m = surfpft_lb,surfpft_ub
+ ft = m-surfpft_lb
+ this%fates(nc)%bc_in(s)%pft_areafrac(ft)=wt_nat_patch(g,t,m)
+ end do
- if(abs(sum(this%fates(nc)%bc_in(s)%pft_areafrac(surfpft_lb:surfpft_ub))-1.0_r8).gt.1.0e-9)then
- write(iulog,*) 'pft_area error in interfc ',s, sum(this%fates(nc)%bc_in(s)%pft_areafrac(:))-1.0_r8
- call endrun(msg=errMsg(sourcefile, __LINE__))
- endif
+ if(abs(sum(this%fates(nc)%bc_in(s)%pft_areafrac(surfpft_lb:surfpft_ub))-1.0_r8).gt.1.0e-9)then
+ write(iulog,*) 'pft_area error in interfc ',s, sum(this%fates(nc)%bc_in(s)%pft_areafrac(:))-1.0_r8
+ call endrun(msg=errMsg(sourcefile, __LINE__))
+ end if
+ end if
+ end if
end do
@@ -911,7 +958,6 @@ subroutine init(this, bounds_proc )
call endrun(msg=errMsg(sourcefile, __LINE__))
end if
-
! Set patch itypes on natural veg columns to nonsense
! This will force a crash if the model outside of FATES tries to think
! of the patch as a PFT.
@@ -934,6 +980,12 @@ subroutine init(this, bounds_proc )
! Fire data to send to FATES
call create_fates_fire_data_method( this%fates_fire_data_method )
+ ! deallocate the local landuse x pft array
+ if (use_fates_fixed_biogeog .and. use_fates_luh) then
+ deallocate(landuse_pft_map)
+ deallocate(landuse_bareground)
+ end if
+
end subroutine init
! ===================================================================================
@@ -1046,7 +1098,7 @@ subroutine dynamics_driv(this, bounds_clump, top_as_inst, &
lnfm24 = this%fates_fire_data_method%GetLight24()
end if
- if (fates_spitfire_mode .eq. anthro_suppression) then
+ if (fates_spitfire_mode == anthro_suppression) then
allocate(gdp_lf_col(bounds_clump%begc:bounds_clump%endc), stat=ier)
if (ier /= 0) then
call endrun(msg="allocation error for gdp"//&
@@ -1066,13 +1118,13 @@ subroutine dynamics_driv(this, bounds_clump, top_as_inst, &
this%fates(nc)%bc_in(s)%lightning24(ifp) = lnfm24(g) * 24._r8 ! #/km2/hr to #/km2/day
- if (fates_spitfire_mode .ge. anthro_ignitions) then
+ if (fates_spitfire_mode >= anthro_ignitions) then
this%fates(nc)%bc_in(s)%pop_density(ifp) = this%fates_fire_data_method%forc_hdm(g)
end if
end do ! ifp
- if (fates_spitfire_mode .eq. anthro_suppression) then
+ if (fates_spitfire_mode == anthro_suppression) then
! Placeholder for future fates use of gdp - comment out before integration
!this%fates(nc)%bc_in(s)%gdp = gdp_lf_col(c) ! k US$/capita(g)
end if
@@ -1151,10 +1203,15 @@ subroutine dynamics_driv(this, bounds_clump, top_as_inst, &
! for now there is one veg column per gridcell, so store all harvest data in each site
! this will eventually change
! the harvest data are zero if today is before the start of the harvest time series
- if (get_do_harvest()) then
+ if (trim(fates_harvest_mode) == fates_harvest_hlmlanduse) then
this%fates(nc)%bc_in(s)%hlm_harvest_rates = harvest_rates(:,g)
this%fates(nc)%bc_in(s)%hlm_harvest_catnames = harvest_varnames
this%fates(nc)%bc_in(s)%hlm_harvest_units = wood_harvest_units
+ else if (trim(fates_harvest_mode) == fates_harvest_luh_area .or. &
+ trim(fates_harvest_mode) == fates_harvest_luh_mass) then
+ this%fates(nc)%bc_in(s)%hlm_harvest_rates = landuse_harvest(:,g)
+ this%fates(nc)%bc_in(s)%hlm_harvest_catnames = landuse_harvest_varnames
+ this%fates(nc)%bc_in(s)%hlm_harvest_units = landuse_harvest_units
end if
this%fates(nc)%bc_in(s)%site_area=col_pp%wtgcell(c)*grc_pp%area(g)*m2_per_km2
@@ -1912,7 +1969,6 @@ end subroutine restart
subroutine init_coldstart(this, canopystate_inst, soilstate_inst, frictionvel_inst)
-
! Arguments
class(hlm_fates_interface_type), intent(inout) :: this
type(canopystate_type) , intent(inout) :: canopystate_inst
@@ -2015,17 +2071,26 @@ subroutine init_coldstart(this, canopystate_inst, soilstate_inst, frictionvel_in
call HydrSiteColdStart(this%fates(nc)%sites,this%fates(nc)%bc_in)
end if
- do s = 1,this%fates(nc)%nsites
- c = this%f2hmap(nc)%fcolumn(s)
- g = col_pp%gridcell(c)
+ ! Transfer initial values to fates
+ if (use_fates_luh) then
+ do s = 1,this%fates(nc)%nsites
+ c = this%f2hmap(nc)%fcolumn(s)
+ g = col_pp%gridcell(c)
+
+ this%fates(nc)%bc_in(s)%hlm_luh_states = landuse_states(:,g)
+ this%fates(nc)%bc_in(s)%hlm_luh_state_names = landuse_state_varnames
+ this%fates(nc)%bc_in(s)%hlm_luh_transitions = landuse_transitions(:,g)
+ this%fates(nc)%bc_in(s)%hlm_luh_transition_names = landuse_transition_varnames
+
+ if (trim(fates_harvest_mode) == fates_harvest_luh_area .or. &
+ trim(fates_harvest_mode) == fates_harvest_luh_mass) then
+ this%fates(nc)%bc_in(s)%hlm_harvest_rates = landuse_harvest(:,g)
+ this%fates(nc)%bc_in(s)%hlm_harvest_catnames = landuse_harvest_varnames
+ this%fates(nc)%bc_in(s)%hlm_harvest_units = landuse_harvest_units
+ end if
- if (use_fates_luh) then
- this%fates(nc)%bc_in(s)%hlm_luh_states = landuse_states(:,g)
- this%fates(nc)%bc_in(s)%hlm_luh_state_names = landuse_state_varnames
- this%fates(nc)%bc_in(s)%hlm_luh_transitions = landuse_transitions(:,g)
- this%fates(nc)%bc_in(s)%hlm_luh_transition_names = landuse_transition_varnames
- end if
- end do
+ end do
+ end if
! Initialize patches
call init_patches(this%fates(nc)%nsites, this%fates(nc)%sites, &
@@ -3608,6 +3673,109 @@ subroutine GetAndSetTime()
end subroutine GetAndSetTime
- !-----------------------------------------------------------------------
+! ======================================================================================
+
+ subroutine GetLandusePFTData(bounds, landuse_pft_file, landuse_pft_map, landuse_bareground)
+
+ ! !DESCRIPTION:
+ ! Read in static landuse x pft file
+
+ ! !USES:
+ use fileutils , only : getfil
+ use ncdio_pio , only : file_desc_t, ncd_io, ncd_inqdlen
+ use ncdio_pio , only : ncd_pio_openfile, ncd_pio_closefile
+ use decompMod , only : BOUNDS_LEVEL_PROC
+ use elm_varcon, only : grlnd
+ use FatesConstantsMod, only : fates_unset_r8
+
+
+ ! !ARGUMENTS:
+ type(bounds_type), intent(in) :: bounds ! proc-level bounds
+ character(len=*) , intent(in) :: landuse_pft_file ! name of file containing static landuse x pft information
+ real(r8), allocatable, intent(inout) :: landuse_pft_map(:,:,:)
+ real(r8), allocatable, intent(inout) :: landuse_bareground(:)
+
+ ! !LOCAL VARIABLES
+ integer :: varnum ! variable number
+ integer :: dimid, dimlen ! dimension id number and length
+ integer :: ier ! error id
+ character(len=256) :: locfn ! local file name
+ type(file_desc_t) :: ncid ! netcdf id
+ real(r8), pointer :: arraylocal(:,:) ! local array for reading fraction data
+ real(r8), pointer :: arraylocal_bareground(:) ! local array for reading bareground data
+ logical :: readvar ! true => variable is on dataset
+ !character(len=16), parameter :: grlnd = 'lndgrid' ! name of lndgrid
+
+ integer, parameter :: dim_landuse_pft = 14
+
+ ! Land use name arrays
+ character(len=10), parameter :: landuse_pft_map_varnames(num_landuse_pft_vars) = &
+ [character(len=10) :: 'frac_primr','frac_secnd','frac_pastr','frac_range'] !need to move 'frac_surf' to a different variable
+
+ character(len=*), parameter :: subname = 'GetLandusePFTData'
+
+ !-----------------------------------------------------------------------
+
+ ! Check to see if the landuse file name has been provided
+ ! Note: getfile checks this as well
+ if (masterproc) then
+ write(iulog,*) 'Attempting to read landuse x pft data .....'
+ if (landuse_pft_file == ' ') then
+ write(iulog,*)'landuse_pft_file must be specified'
+ call endrun(msg=errMsg(__FILE__, __LINE__))
+ endif
+ endif
+
+ ! Initialize the landuse x pft arrays and initialize to unset
+ allocate(landuse_pft_map(bounds%begg:bounds%endg,dim_landuse_pft,num_landuse_pft_vars),stat=ier)
+ if (ier /= 0) then
+ call endrun(msg=' allocation error for landuse_pft_map'//errMsg(__FILE__, __LINE__))
+ end if
+ landuse_pft_map = fates_unset_r8
+
+ allocate(landuse_bareground(bounds%begg:bounds%endg),stat=ier)
+ if (ier /= 0) then
+ call endrun(msg=' allocation error for landuse_bareground'//errMsg(__FILE__, __LINE__))
+ end if
+ landuse_bareground = fates_unset_r8
+
+
+ ! Get the local filename and open the file
+ call getfil(landuse_pft_file, locfn, 0)
+ call ncd_pio_openfile (ncid, trim(locfn), 0)
+
+ ! Check that natpft dimension on the file matches the target array dimensions
+ call ncd_inqdlen(ncid, dimid, dimlen, 'natpft')
+ if (dimlen /= dim_landuse_pft) then
+ write(iulog,*) 'natpft dimensions on the landuse x pft file do not match target array size'
+ call endrun(msg=errMsg(__FILE__, __LINE__))
+ end if
+
+ ! Allocate a temporary array since ncdio expects a pointer
+ allocate(arraylocal(bounds%begg:bounds%endg,dim_landuse_pft))
+ allocate(arraylocal_bareground(bounds%begg:bounds%endg))
+
+ ! Read the landuse x pft data from file
+ do varnum = 1, num_landuse_pft_vars
+ call ncd_io(ncid=ncid, varname=landuse_pft_map_varnames(varnum), flag='read', &
+ data=arraylocal, dim1name=grlnd, readvar=readvar)
+ if (.not. readvar) &
+ call endrun(msg='ERROR: '//trim(landuse_pft_map_varnames(varnum))// &
+ ' NOT on landuse x pft file'//errMsg(__FILE__, __LINE__))
+ landuse_pft_map(bounds%begg:bounds%endg,:,varnum) = arraylocal(bounds%begg:bounds%endg,:)
+ end do
+
+ ! Read the bareground data from file. This is per gridcell only.
+ call ncd_io(ncid=ncid, varname='frac_brgnd', flag='read', &
+ data=arraylocal_bareground, dim1name=grlnd, readvar=readvar)
+ if (.not. readvar) call endrun(msg='ERROR: frac_brgnd NOT on landuse x pft file'//errMsg(__FILE__, __LINE__))
+ landuse_bareground(bounds%begg:bounds%endg) = arraylocal_bareground(bounds%begg:bounds%endg)
+
+ ! Deallocate the temporary local array point and close the file
+ deallocate(arraylocal)
+ deallocate(arraylocal_bareground)
+ call ncd_pio_closefile(ncid)
+
+ end subroutine GetLandusePFTData
end module ELMFatesInterfaceMod