diff --git a/cime_config/tests.py b/cime_config/tests.py
index 5e94f9c30073..f75032ef3349 100644
--- a/cime_config/tests.py
+++ b/cime_config/tests.py
@@ -415,6 +415,7 @@
"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",
diff --git a/components/elm/bld/ELMBuildNamelist.pm b/components/elm/bld/ELMBuildNamelist.pm
index 4e5818e6963b..c6214323525b 100755
--- a/components/elm/bld/ELMBuildNamelist.pm
+++ b/components/elm/bld/ELMBuildNamelist.pm
@@ -797,7 +797,8 @@ sub setup_cmdl_fates_mode {
"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_parteh_mode","use_fates_cohort_age_tracking","use_snicar_ad", "use_fates_luh",
+ "fluh_timeseries");
foreach my $var ( @list ) {
if ( defined($nl->get_value($var)) ) {
$nl_flags->{$var} = $nl->get_value($var);
@@ -857,6 +858,10 @@ 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_luh";
+ 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");
@@ -3292,8 +3297,43 @@ sub setup_logic_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'});
+
+ # 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";
+ 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)) ) {
+ 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 ) {
+ fatal_error('fates_spitfire_mode can NOT be set to greater than 0 when use_fates_sp is true');
+ }
+ }
+ }
+ # check that fates landuse change mode has the necessary luh2 landuse timeseries data
+ 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 );
+ 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("$fname 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 4f02fc9df8ac..d267252fd3a6 100644
--- a/components/elm/bld/namelist_files/namelist_defaults.xml
+++ b/components/elm/bld/namelist_files/namelist_defaults.xml
@@ -127,7 +127,7 @@ attributes from the config_cache.xml file (with keys converted to upper-case).
-lnd/clm2/paramdata/fates_params_api25.5.0_12pft_c230710.nc
+lnd/clm2/paramdata/fates_params_api.32.0.0_12pft_c231215.nc
lnd/clm2/paramdata/CNP_parameters_c131108.nc
@@ -565,6 +565,11 @@ 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
+
+
@@ -2136,6 +2141,7 @@ this mask will have smb calculated over the entire global land surface
.false.
.false.
.false.
+.false.
1
0
.false.
diff --git a/components/elm/bld/namelist_files/namelist_definition.xml b/components/elm/bld/namelist_files/namelist_definition.xml
index 1353f8b84b64..45a419edb99a 100644
--- a/components/elm/bld/namelist_files/namelist_definition.xml
+++ b/components/elm/bld/namelist_files/namelist_definition.xml
@@ -381,6 +381,21 @@ Toggle to turn on inventory initialization(only relevant if FATES is being used)
Full pathname to the inventory initialization control file.
+
+
+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.)
+(Also, only valid for use_fates = true and is incompatible with transient runs currently.)
+
+
+
+
+Full pathname of unified land use harmonization data file. This causes the land-use
+types to vary over time.
+
+
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 9b07b504564b..cd078b90950c 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,10 +16,8 @@ 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_DISTURBANCE_RATE_P2P', 'FATES_DISTURBANCE_RATE_P2S',
-'FATES_DISTURBANCE_RATE_S2S', 'FATES_DISTURBANCE_RATE_FIRE',
+'FATES_HARVEST_CARBON_FLUX', 'FATES_DISTURBANCE_RATE_FIRE',
'FATES_DISTURBANCE_RATE_LOGGING', 'FATES_DISTURBANCE_RATE_TREEFALL',
-'FATES_DISTURBANCE_RATE_POTENTIAL', 'FATES_HARVEST_CARBON_FLUX',
'FATES_STOMATAL_COND', 'FATES_LBLAYER_COND', 'FATES_NPP', 'FATES_GPP',
'FATES_AUTORESP', 'FATES_GROWTH_RESP', 'FATES_MAINT_RESP', 'FATES_GPP_CANOPY',
'FATES_AUTORESP_CANOPY', 'FATES_GPP_USTORY', 'FATES_AUTORESP_USTORY',
@@ -28,4 +26,5 @@ hist_fincl1 = 'FATES_NCOHORTS', 'FATES_TRIMMING', 'FATES_AREA_PLANTS',
'FATES_NEP', 'FATES_HET_RESP', 'FATES_FIRE_CLOSS', 'FATES_FIRE_FLUX_EL',
'FATES_CBALANCE_ERROR', 'FATES_ERROR_EL', 'FATES_LEAF_ALLOC',
'FATES_SEED_ALLOC', 'FATES_STEM_ALLOC', 'FATES_FROOT_ALLOC',
-'FATES_CROOT_ALLOC', 'FATES_STORE_ALLOC'
+'FATES_CROOT_ALLOC', 'FATES_STORE_ALLOC',
+'FATES_PATCHAREA_LU', 'FATES_DISTURBANCE_RATE_MATRIX_LULU'
diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_landuse/include_user_mods b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_landuse/include_user_mods
new file mode 100644
index 000000000000..45e8af32d22a
--- /dev/null
+++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_landuse/include_user_mods
@@ -0,0 +1 @@
+../fates_cold
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
new file mode 100644
index 000000000000..098d4fd33a38
--- /dev/null
+++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_landuse/user_nl_elm
@@ -0,0 +1,2 @@
+flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_map/landuse.timeseries_4x5_hist_simyr1850-2015_200311.nc'
+do_harvest = .true.
diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_luh2/include_user_mods b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_luh2/include_user_mods
new file mode 100644
index 000000000000..45e8af32d22a
--- /dev/null
+++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_luh2/include_user_mods
@@ -0,0 +1 @@
+../fates_cold
diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_luh2/shell_commands b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_luh2/shell_commands
new file mode 100644
index 000000000000..e02188057ce6
--- /dev/null
+++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_luh2/shell_commands
@@ -0,0 +1 @@
+./xmlchange TEST_MEMLEAK_TOLERANCE=0.2
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
new file mode 100644
index 000000000000..854c21407f1a
--- /dev/null
+++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_luh2/user_nl_elm
@@ -0,0 +1 @@
+use_fates_luh = .true.
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 407d0dcecf2a..8dc47347ed88 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
@@ -19,10 +19,8 @@ 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_DISTURBANCE_RATE_P2P', 'FATES_DISTURBANCE_RATE_P2S',
-'FATES_DISTURBANCE_RATE_S2S', 'FATES_DISTURBANCE_RATE_FIRE',
+'FATES_HARVEST_CARBON_FLUX', 'FATES_DISTURBANCE_RATE_FIRE',
'FATES_DISTURBANCE_RATE_LOGGING', 'FATES_DISTURBANCE_RATE_TREEFALL',
-'FATES_DISTURBANCE_RATE_POTENTIAL', 'FATES_HARVEST_CARBON_FLUX',
'FATES_STOMATAL_COND', 'FATES_LBLAYER_COND', 'FATES_NPP', 'FATES_GPP',
'FATES_AUTORESP', 'FATES_GROWTH_RESP', 'FATES_MAINT_RESP', 'FATES_GPP_CANOPY',
'FATES_AUTORESP_CANOPY', 'FATES_GPP_USTORY', 'FATES_AUTORESP_USTORY',
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 9b07b504564b..4812969a278b 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,10 +16,8 @@ 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_DISTURBANCE_RATE_P2P', 'FATES_DISTURBANCE_RATE_P2S',
-'FATES_DISTURBANCE_RATE_S2S', 'FATES_DISTURBANCE_RATE_FIRE',
+'FATES_HARVEST_CARBON_FLUX', 'FATES_DISTURBANCE_RATE_FIRE',
'FATES_DISTURBANCE_RATE_LOGGING', 'FATES_DISTURBANCE_RATE_TREEFALL',
-'FATES_DISTURBANCE_RATE_POTENTIAL', 'FATES_HARVEST_CARBON_FLUX',
'FATES_STOMATAL_COND', 'FATES_LBLAYER_COND', 'FATES_NPP', 'FATES_GPP',
'FATES_AUTORESP', 'FATES_GROWTH_RESP', 'FATES_MAINT_RESP', 'FATES_GPP_CANOPY',
'FATES_AUTORESP_CANOPY', 'FATES_GPP_USTORY', 'FATES_AUTORESP_USTORY',
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 30a0dbb88cb0..92bfa49d87ce 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
@@ -19,10 +19,8 @@ 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_DISTURBANCE_RATE_P2P', 'FATES_DISTURBANCE_RATE_P2S',
-'FATES_DISTURBANCE_RATE_S2S', 'FATES_DISTURBANCE_RATE_FIRE',
+'FATES_HARVEST_CARBON_FLUX', 'FATES_DISTURBANCE_RATE_FIRE',
'FATES_DISTURBANCE_RATE_LOGGING', 'FATES_DISTURBANCE_RATE_TREEFALL',
-'FATES_DISTURBANCE_RATE_POTENTIAL', 'FATES_HARVEST_CARBON_FLUX',
'FATES_STOMATAL_COND', 'FATES_LBLAYER_COND', 'FATES_NPP', 'FATES_GPP',
'FATES_AUTORESP', 'FATES_GROWTH_RESP', 'FATES_MAINT_RESP', 'FATES_GPP_CANOPY',
'FATES_AUTORESP_CANOPY', 'FATES_GPP_USTORY', 'FATES_AUTORESP_USTORY',
diff --git a/components/elm/src/biogeophys/SurfaceAlbedoMod.F90 b/components/elm/src/biogeophys/SurfaceAlbedoMod.F90
index 2b3666b5157f..073c836c19bc 100644
--- a/components/elm/src/biogeophys/SurfaceAlbedoMod.F90
+++ b/components/elm/src/biogeophys/SurfaceAlbedoMod.F90
@@ -754,13 +754,16 @@ subroutine SurfaceAlbedo(bounds, &
ws(p) = esai(p) / max( elai(p)+esai(p), mpe )
end do
- do ib = 1, numrad
- do fp = 1,num_vegsol
- p = filter_vegsol(fp)
- rho(p,ib) = max( rhol(veg_pp%itype(p),ib)*wl(p) + rhos(veg_pp%itype(p),ib)*ws(p), mpe )
- tau(p,ib) = max( taul(veg_pp%itype(p),ib)*wl(p) + taus(veg_pp%itype(p),ib)*ws(p), mpe )
+ ! rho and tau are not needed if fates is on
+ if (.not. use_fates) then
+ do ib = 1, numrad
+ do fp = 1,num_vegsol
+ p = filter_vegsol(fp)
+ rho(p,ib) = max( rhol(veg_pp%itype(p),ib)*wl(p) + rhos(veg_pp%itype(p),ib)*ws(p), mpe )
+ tau(p,ib) = max( taul(veg_pp%itype(p),ib)*wl(p) + taus(veg_pp%itype(p),ib)*ws(p), mpe )
+ end do
end do
- end do
+ end if
! Diagnose number of canopy layers for radiative transfer, in increments of dincmax.
! Add to number of layers so long as cumulative leaf+stem area does not exceed total
diff --git a/components/elm/src/dyn_subgrid/dynFATESLandUseChangeMod.F90 b/components/elm/src/dyn_subgrid/dynFATESLandUseChangeMod.F90
new file mode 100644
index 000000000000..53be7987182e
--- /dev/null
+++ b/components/elm/src/dyn_subgrid/dynFATESLandUseChangeMod.F90
@@ -0,0 +1,197 @@
+module dynFATESLandUseChangeMod
+
+#include "shr_assert.h"
+
+ !---------------------------------------------------------------------------
+ ! !DESCRIPTION:
+ ! Handle reading of the land use harmonization (LUH2) dataset
+
+ ! !USES:
+ use shr_kind_mod , only : r8 => shr_kind_r8
+ use shr_log_mod , only : errMsg => shr_log_errMsg
+ use decompMod , only : bounds_type, BOUNDS_LEVEL_PROC
+ use abortutils , only : endrun
+ use dynFileMod , only : dyn_file_type
+ use dynVarTimeUninterpMod , only : dyn_var_time_uninterp_type
+ use elm_varcon , only : grlnd
+ use elm_varctl , only : iulog
+
+ implicit none
+
+ private
+
+ real(r8), allocatable, public :: landuse_transitions(:,:)
+ real(r8), allocatable, public :: landuse_states(:,:)
+
+ integer, public, parameter :: num_landuse_transition_vars = 108
+ integer, public, parameter :: num_landuse_state_vars = 12
+
+ type(dyn_file_type), target :: dynFatesLandUse_file
+
+ ! Land use name arrays
+ character(len=5), public, parameter :: landuse_state_varnames(num_landuse_state_vars) = &
+ [character(len=5) :: 'primf', & ! forested primary land
+ 'primn', & ! non-forested primary land
+ 'secdf', & ! potentially forested secondary land
+ 'secdn', & ! potentially non-forested secondary land
+ 'pastr', & ! managed pasture
+ 'range', & ! rangeland
+ 'urban', & ! urban land
+ 'c3ann', & ! C3 annual crops
+ 'c4ann', & ! C4 annual crops
+ 'c3per', & ! C3 perennial crops
+ 'c4per', & ! C4 perennial crops
+ 'c3nfx'] ! C3 nitrogen-fixing crops
+
+ character(len=14), public, parameter :: landuse_transition_varnames(num_landuse_transition_vars) = &
+ [character(len=14) :: 'primf_to_secdn','primf_to_pastr','primf_to_range','primf_to_urban', &
+ 'primf_to_c3ann','primf_to_c4ann','primf_to_c3per','primf_to_c4per','primf_to_c3nfx', &
+ 'primn_to_secdf','primn_to_pastr','primn_to_range','primn_to_urban', &
+ 'primn_to_c3ann','primn_to_c4ann','primn_to_c3per','primn_to_c4per','primn_to_c3nfx', &
+ 'secdf_to_secdn','secdf_to_pastr','secdf_to_range','secdf_to_urban', &
+ 'secdf_to_c3ann','secdf_to_c4ann','secdf_to_c3per','secdf_to_c4per','secdf_to_c3nfx', &
+ 'secdn_to_secdf','secdn_to_pastr','secdn_to_range','secdn_to_urban', &
+ 'secdn_to_c3ann','secdn_to_c4ann','secdn_to_c3per','secdn_to_c4per','secdn_to_c3nfx', &
+ 'pastr_to_secdf','pastr_to_secdn','pastr_to_range','pastr_to_urban', &
+ 'pastr_to_c3ann','pastr_to_c4ann','pastr_to_c3per','pastr_to_c4per','pastr_to_c3nfx', &
+ 'range_to_secdf','range_to_secdn','range_to_pastr','range_to_urban', &
+ 'range_to_c3ann','range_to_c4ann','range_to_c3per','range_to_c4per','range_to_c3nfx', &
+ 'urban_to_secdf','urban_to_secdn','urban_to_pastr','urban_to_range', &
+ 'urban_to_c3ann','urban_to_c4ann','urban_to_c3per','urban_to_c4per','urban_to_c3nfx', &
+ 'c3ann_to_c4ann','c3ann_to_c3per','c3ann_to_c4per','c3ann_to_c3nfx', &
+ 'c3ann_to_secdf','c3ann_to_secdn','c3ann_to_pastr','c3ann_to_range','c3ann_to_urban', &
+ 'c4ann_to_c3ann','c4ann_to_c3per','c4ann_to_c4per','c4ann_to_c3nfx', &
+ 'c4ann_to_secdf','c4ann_to_secdn','c4ann_to_pastr','c4ann_to_range','c4ann_to_urban', &
+ 'c3per_to_c3ann','c3per_to_c4ann','c3per_to_c4per','c3per_to_c3nfx', &
+ 'c3per_to_secdf','c3per_to_secdn','c3per_to_pastr','c3per_to_range','c3per_to_urban', &
+ 'c4per_to_c3ann','c4per_to_c4ann','c4per_to_c3per','c4per_to_c3nfx', &
+ 'c4per_to_secdf','c4per_to_secdn','c4per_to_pastr','c4per_to_range','c4per_to_urban', &
+ '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
+
+ public :: dynFatesLandUseInit
+ public :: dynFatesLandUseInterp
+
+contains
+
+ !-----------------------------------------------------------------------
+ subroutine dynFatesLandUseInit(bounds, landuse_filename)
+
+ ! !DESCRIPTION:
+ ! Initialize data structures for land use information.
+
+ ! !USES:
+ use elm_varctl , only : use_fates_luh
+ 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
+
+ ! !LOCAL VARIABLES
+ integer :: varnum, i ! counter for harvest variables
+ integer :: landuse_shape(1) ! land use shape
+ integer :: num_points ! number of spatial points
+ integer :: ier ! error code
+ real(r8), allocatable :: this_data(:) ! data for a single harvest variable
+ !
+ character(len=*), parameter :: subname = 'dynFatesLandUseInit'
+ !-----------------------------------------------------------------------
+
+ SHR_ASSERT_ALL(bounds%level == BOUNDS_LEVEL_PROC, subname // ': argument must be PROC-level bounds')
+
+ ! Allocate and initialize the land use arrays
+ allocate(landuse_states(num_landuse_state_vars,bounds%begg:bounds%endg),stat=ier)
+ if (ier /= 0) then
+ call endrun(msg=' allocation error for landuse_states'//errMsg(__FILE__, __LINE__))
+ end if
+ allocate(landuse_transitions(num_landuse_transition_vars,bounds%begg:bounds%endg),stat=ier)
+ if (ier /= 0) then
+ call endrun(msg=' allocation error for landuse_transitions'//errMsg(__FILE__, __LINE__))
+ end if
+
+ landuse_states = 0._r8
+ landuse_transitions = 0._r8
+
+ 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
+
+
+ !-----------------------------------------------------------------------
+ subroutine dynFatesLandUseInterp(bounds, init_state)
+
+ use dynTimeInfoMod , only : time_info_type
+
+ ! !ARGUMENTS:
+ type(bounds_type), intent(in) :: bounds ! proc-level bounds
+ logical, optional, intent(in) :: init_state ! fates needs state for initialization
+
+ ! !LOCAL VARIABLES:
+ integer :: varnum
+ integer :: i
+ logical :: init_flag
+ real(r8), allocatable :: this_data(:)
+ character(len=*), parameter :: subname = 'dynFatesLandUseInterp'
+ !-----------------------------------------------------------------------
+ SHR_ASSERT_ALL(bounds%level == BOUNDS_LEVEL_PROC, subname // ': argument must be PROC-level bounds')
+
+ init_flag = .false.
+ if (present(init_state)) then
+ 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)
+
+ 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
+ else
+ ! Right now we don't account for the topounits
+ allocate(this_data(bounds%begg:bounds%endg))
+ do varnum = 1, num_landuse_transition_vars
+ call landuse_transition_vars(varnum)%get_current_data(this_data)
+ landuse_transitions(varnum,bounds%begg:bounds%endg) = this_data(bounds%begg:bounds%endg)
+ end do
+ do varnum = 1, num_landuse_state_vars
+ 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
+ deallocate(this_data)
+ end if
+
+ end subroutine dynFatesLandUseInterp
+
+end module dynFATESLandUseChangeMod
diff --git a/components/elm/src/dyn_subgrid/dynSubgridDriverMod.F90 b/components/elm/src/dyn_subgrid/dynSubgridDriverMod.F90
index 479ee5ab5518..8ac0cf4c45e7 100644
--- a/components/elm/src/dyn_subgrid/dynSubgridDriverMod.F90
+++ b/components/elm/src/dyn_subgrid/dynSubgridDriverMod.F90
@@ -153,7 +153,8 @@ subroutine dynSubgrid_driver(bounds_proc, &
! OUTSIDE any loops over clumps in the driver.
!
! !USES:
- use elm_varctl , only : use_cn, create_glacier_mec_landunit, use_fates
+ use elm_varctl , only : use_cn, create_glacier_mec_landunit
+ use elm_varctl , only : use_fates, use_fates_luh
use decompMod , only : bounds_type, get_proc_clumps, get_clump_bounds
use decompMod , only : BOUNDS_LEVEL_PROC
use dynInitColumnsMod , only : initialize_new_columns
@@ -161,6 +162,9 @@ subroutine dynSubgrid_driver(bounds_proc, &
use dynConsBiogeochemMod , only : dyn_cnbal_patch, dyn_cnbal_column
use dynpftFileMod , only : dynpft_interp
use dynHarvestMod , only : dynHarvest_interp_harvest_types
+
+ use dynFATESLandUseChangeMod, only : dynFatesLandUseInterp
+
use dynEDMod , only : dyn_ED
use reweightMod , only : reweight_wrapup
use subgridWeightsMod , only : compute_higher_order_weights, set_subgrid_diagnostic_fields
@@ -244,6 +248,10 @@ subroutine dynSubgrid_driver(bounds_proc, &
call dynHarvest_interp_harvest_types(bounds_proc)
end if
+ if (use_fates_luh) then
+ call dynFatesLandUseInterp(bounds_proc)
+ end if
+
! ==========================================================================
! Do everything else related to land cover change
! ==========================================================================
diff --git a/components/elm/src/external_models/fates b/components/elm/src/external_models/fates
index 0b105bec7a90..698a8df848ec 160000
--- a/components/elm/src/external_models/fates
+++ b/components/elm/src/external_models/fates
@@ -1 +1 @@
-Subproject commit 0b105bec7a90c5e02d1098f9bbdcf255f358aaa4
+Subproject commit 698a8df848ecdb81aa72fee6c86be2c41b2545e9
diff --git a/components/elm/src/main/controlMod.F90 b/components/elm/src/main/controlMod.F90
index 51e0b2898417..3b8c08be31bd 100755
--- a/components/elm/src/main/controlMod.F90
+++ b/components/elm/src/main/controlMod.F90
@@ -259,6 +259,8 @@ subroutine control_init( )
use_fates_fixed_biogeog, &
use_fates_nocomp, &
use_fates_sp, &
+ use_fates_luh, &
+ fluh_timeseries, &
fates_parteh_mode, &
fates_seeddisp_cadence, &
use_fates_tree_damage
@@ -800,6 +802,7 @@ subroutine control_spmd()
call mpi_bcast (fates_spitfire_mode, 1, MPI_INTEGER, 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 (use_fates_planthydro, 1, MPI_LOGICAL, 0, mpicom, ier)
call mpi_bcast (use_fates_cohort_age_tracking, 1, MPI_LOGICAL, 0, mpicom, ier)
@@ -807,6 +810,7 @@ subroutine control_spmd()
call mpi_bcast (use_fates_fixed_biogeog, 1, MPI_LOGICAL, 0, mpicom, ier)
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_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), &
@@ -1213,6 +1217,7 @@ subroutine control_print ()
write(iulog, *) ' fates_spitfire_mode = ', fates_spitfire_mode
write(iulog, *) ' use_fates_logging = ', use_fates_logging
write(iulog, *) ' fates_paramfile = ', fates_paramfile
+ write(iulog, *) ' fluh_timeseries = ', fluh_timeseries
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
@@ -1223,6 +1228,7 @@ subroutine control_print ()
write(iulog, *) ' use_fates_fixed_biogeog = ', use_fates_fixed_biogeog
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, *) ' 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_initializeMod.F90 b/components/elm/src/main/elm_initializeMod.F90
index 2a8079692379..86e72030b946 100755
--- a/components/elm/src/main/elm_initializeMod.F90
+++ b/components/elm/src/main/elm_initializeMod.F90
@@ -12,8 +12,8 @@ module elm_initializeMod
use elm_varctl , only : nsrest, nsrStartup, nsrContinue, nsrBranch
use elm_varctl , only : create_glacier_mec_landunit, iulog
use elm_varctl , only : use_lch4, use_cn, use_voc, use_c13, use_c14
- use elm_varctl , only : use_fates, use_betr, use_fates_sp, use_fan
- use elm_varsur , only : wt_lunit, urban_valid, wt_nat_patch, wt_cft, wt_glc_mec, topo_glc_mec,firrig,f_surf,f_grd
+ use elm_varctl , only : use_fates, use_betr, use_fates_sp, use_fan, use_fates_luh
+ use elm_varsur , only : wt_lunit, urban_valid, wt_nat_patch, wt_cft, wt_glc_mec, topo_glc_mec,firrig,f_surf,f_grd
use elm_varsur , only : fert_cft, fert_p_cft
use elm_varsur , only : wt_tunit, elv_tunit, slp_tunit,asp_tunit,num_tunit_per_grd
use perf_mod , only : t_startf, t_stopf
@@ -468,6 +468,7 @@ subroutine initialize2( )
use elm_time_manager , only : get_curr_date, get_nstep, advance_timestep
use elm_time_manager , only : timemgr_init, timemgr_restart_io, timemgr_restart
use controlMod , only : nlfilename
+ use controlMod , only : fluh_timeseries
use decompMod , only : get_proc_clumps, get_proc_bounds, get_clump_bounds, bounds_type
use domainMod , only : ldomain
use initInterpMod , only : initInterp
@@ -508,6 +509,7 @@ subroutine initialize2( )
use ELMFatesInterfaceMod , only: ELMFatesTimesteps
use FATESFireFactoryMod , only : scalar_lightning
use FanStreamMod , only : fanstream_init, fanstream_interp
+ use dynFATESLandUseChangeMod, only : dynFatesLandUseInit
!
! !ARGUMENTS
implicit none
@@ -734,6 +736,11 @@ subroutine initialize2( )
call dynSubgrid_init(bounds_proc, glc2lnd_vars, crop_vars)
call t_stopf('init_dyn_subgrid')
+ ! Initialize fates LUH2 usage
+ if (use_fates_luh) then
+ call dynFatesLandUseInit(bounds_proc, fluh_timeseries)
+ end if
+
! ------------------------------------------------------------------------
! Initialize modules (after time-manager initialization in most cases)
! ------------------------------------------------------------------------
diff --git a/components/elm/src/main/elm_varctl.F90 b/components/elm/src/main/elm_varctl.F90
index e1d26775a5dc..d5a61da8fdbf 100644
--- a/components/elm/src/main/elm_varctl.F90
+++ b/components/elm/src/main/elm_varctl.F90
@@ -229,8 +229,10 @@ module elm_varctl
logical, public :: use_fates_ed_st3 = .false. ! true => static stand structure
logical, public :: use_fates_ed_prescribed_phys = .false. ! true => prescribed physiology
logical, public :: use_fates_inventory_init = .false. ! true => initialize fates from inventory
- logical, public :: use_fates_nocomp = .false. ! true => use no comopetition mode
- logical, public :: use_fates_sp = .false. ! true => use FATES satellite phenology mode
+ 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
+ character(len=256), public :: fluh_timeseries = '' ! filename for land use harmonization 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 a7aec9e85933..edcdd01f1ede 100644
--- a/components/elm/src/main/elmfates_interfaceMod.F90
+++ b/components/elm/src/main/elmfates_interfaceMod.F90
@@ -55,6 +55,7 @@ module ELMFatesInterfaceMod
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_tree_damage
use elm_varctl , only : nsrest, nsrBranch
use elm_varctl , only : fates_inventory_ctrl_filename
@@ -73,7 +74,8 @@ module ELMFatesInterfaceMod
use elm_varpar , only : nlevdecomp_full
use elm_varpar , only : i_met_lit, i_cel_lit, i_lig_lit
use elm_varpar , only : surfpft_lb, surfpft_ub
- use elm_varpar , only : natpft_size, cft_size
+ use elm_varpar , only : natpft_size, max_patch_per_col, maxpatch_urb
+ use elm_varpar , only : numcft, maxpatch_urb
use PhotosynthesisType , only : photosyns_type
Use TopounitDataType , only : topounit_atmospheric_flux, topounit_atmospheric_state
use atm2lndType , only : atm2lnd_type
@@ -134,6 +136,7 @@ module ELMFatesInterfaceMod
use FatesInterfaceMod , only : DetermineGridCellNeighbors
use FatesHistoryInterfaceMod, only : fates_hist
use FatesRestartInterfaceMod, only : fates_restart_interface_type
+ use FatesInterfaceTypesMod, only : hlm_num_luh2_states
use PRTGenericMod , only : num_elements
use FatesPatchMod , only : fates_patch_type
@@ -166,14 +169,17 @@ module ELMFatesInterfaceMod
anthro_ignitions, anthro_suppression
use dynHarvestMod , only : num_harvest_vars, harvest_varnames, wood_harvest_units
- use dynHarvestMod , only : harvest_rates ! these are dynamic in space and time
-
+ 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 dynSubgridControlMod, only : get_do_harvest ! this gets the namelist value
+ 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 FatesInterfaceTypesMod , only : bc_in_type, bc_out_type
+ use FatesInterfaceTypesMod , only : bc_in_type, bc_out_type
use ELMFatesParamInterfaceMod, only : fates_param_reader_ctsm_impl
use FatesParametersInterface, only : fates_param_reader_type
@@ -351,7 +357,7 @@ subroutine ELMFatesGlobals1()
call SetFatesGlobalElements1(use_fates,natpft_size,0,var_reader)
natpft_size = fates_maxPatchesPerSite
-
+ max_patch_per_col= max(natpft_size, numcft, maxpatch_urb)
return
end subroutine ELMFatesGlobals1
@@ -382,7 +388,9 @@ subroutine ELMFatesGlobals2()
integer :: pass_num_lu_harvest_types
integer :: pass_lu_harvest
integer :: pass_tree_damage
-
+ integer :: pass_use_luh
+ integer :: pass_num_luh_states
+ integer :: pass_num_luh_transitions
! ----------------------------------------------------------------------------------
! FATES lightning definitions
! 1 : use a global constant lightning rate found in fates_params.
@@ -507,11 +515,23 @@ subroutine ELMFatesGlobals2()
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('use_logging',ival=pass_logging)
+ 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
+ else
+ pass_use_luh = 0
+ 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_ed_st3) then
pass_ed_st3 = 1
else
@@ -747,7 +767,9 @@ subroutine init(this, bounds_proc )
ndecomp = 1
end if
- call allocate_bcin(this%fates(nc)%bc_in(s),col_pp%nlevbed(c),ndecomp,num_harvest_vars,surfpft_lb,surfpft_ub)
+ call allocate_bcin(this%fates(nc)%bc_in(s), col_pp%nlevbed(c), ndecomp, &
+ num_harvest_vars, num_landuse_state_vars, num_landuse_transition_vars, &
+ surfpft_lb, surfpft_ub)
call allocate_bcout(this%fates(nc)%bc_out(s),col_pp%nlevbed(c),ndecomp)
call zero_bcs(this%fates(nc),s)
@@ -870,7 +892,7 @@ subroutine dynamics_driv(this, bounds_clump, top_as_inst, &
top_af_inst, atm2lnd_inst, soilstate_inst, &
canopystate_inst, frictionvel_inst, soil_water_retention_curve )
- use FatesConstantsMod , only : m2_per_km2
+ use FatesConstantsMod , only : m2_per_km2
! This wrapper is called daily from clm_driver
! This wrapper calls ed_driver, which is the daily dynamics component of FATES
@@ -889,7 +911,7 @@ subroutine dynamics_driv(this, bounds_clump, top_as_inst, &
class(soil_water_retention_curve_type), intent(in) :: soil_water_retention_curve
! !LOCAL VARIABLES:
- integer :: s ! site index
+ integer :: s, i ! site index
integer :: c ! column index (HLM)
integer :: j ! Soil layer index
integer :: t ! topounit index (HLM)
@@ -905,6 +927,8 @@ subroutine dynamics_driv(this, bounds_clump, top_as_inst, &
real(r8), pointer :: lnfm24(:) ! 24-hour averaged lightning data
real(r8), pointer :: gdp_lf_col(:) ! gdp data
+ logical :: do_landuse_update ! local flag to pass transitions update to fates
+
!-----------------------------------------------------------------------
@@ -1048,6 +1072,13 @@ subroutine dynamics_driv(this, bounds_clump, top_as_inst, &
end if
this%fates(nc)%bc_in(s)%site_area=col_pp%wtgcell(c)*grc_pp%area(g)*m2_per_km2
+ 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
! Nutrient uptake fluxes have been accumulating with each short
@@ -1805,11 +1836,12 @@ subroutine init_coldstart(this, canopystate_inst, soilstate_inst, frictionvel_in
real(r8) :: vol_ice
real(r8) :: eff_porosity
integer :: nlevsoil
- integer :: j
+ integer :: j, i
integer :: s
- integer :: c
+ integer :: c, g
integer :: p ! HLM patch index
integer :: ft ! plant functional type
+ logical :: do_landuse_update ! local flag to pass transitions update to fates
! Set the FATES global time and date variables
call GetAndSetTime
@@ -1859,7 +1891,6 @@ subroutine init_coldstart(this, canopystate_inst, soilstate_inst, frictionvel_in
if (use_fates_planthydro) then
do s = 1,this%fates(nc)%nsites
-
c = this%f2hmap(nc)%fcolumn(s)
nlevsoil = this%fates(nc)%bc_in(s)%nlevsoil
@@ -1893,9 +1924,23 @@ 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)
+
+ 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
+
+ ! Initialize patches
call init_patches(this%fates(nc)%nsites, this%fates(nc)%sites, &
this%fates(nc)%bc_in)
+
do s = 1,this%fates(nc)%nsites
c = this%f2hmap(nc)%fcolumn(s)
@@ -2946,6 +2991,7 @@ subroutine init_history_io(this,bounds_proc)
use FatesIOVariableKindMod, only : site_coage_r8, site_coage_pft_r8
use FatesIOVariableKindMod, only : site_can_r8, site_cnlf_r8, site_cnlfpft_r8
use FatesIOVariableKindMod, only : site_cdpf_r8, site_cdsc_r8, site_cdam_r8
+ use FatesIOVariableKindMod, only : site_landuse_r8, site_lulu_r8
use FatesIODimensionsMod, only : fates_bounds_type
@@ -3044,7 +3090,8 @@ subroutine init_history_io(this,bounds_proc)
site_can_r8,site_cnlf_r8, site_cnlfpft_r8, site_scag_r8, &
site_scagpft_r8, site_agepft_r8, site_elem_r8, site_elpft_r8, &
site_elcwd_r8, site_elage_r8, site_coage_r8, site_coage_pft_r8, &
- site_agefuel_r8,site_cdsc_r8, site_cdpf_r8, site_cdam_r8)
+ site_agefuel_r8,site_cdsc_r8, site_cdpf_r8, site_cdam_r8, &
+ site_landuse_r8, site_lulu_r8)
d_index = fates_hist%dim_kinds(dk_index)%dim2_index
dim2name = fates_hist%dim_bounds(d_index)%name
@@ -3311,6 +3358,7 @@ subroutine hlm_bounds_to_fates_bounds(hlm, fates)
use EDParamsMod, only : nclmax_fates => nclmax
use FatesInterfaceTypesMod, only : numpft_fates => numpft
use FatesInterfaceTypesMod, only : nlevcoage
+ use FatesConstantsMod, only : n_landuse_cats
implicit none
@@ -3395,6 +3443,12 @@ subroutine hlm_bounds_to_fates_bounds(hlm, fates)
fates%agefuel_begin = 1
fates%agefuel_end = nlevage_fates * nfsc_fates
+ fates%landuse_begin = 1
+ fates%landuse_end = n_landuse_cats
+
+ fates%lulu_begin = 1
+ fates%lulu_end = n_landuse_cats * n_landuse_cats
+
end subroutine hlm_bounds_to_fates_bounds
! ======================================================================================
diff --git a/components/elm/src/main/histFileMod.F90 b/components/elm/src/main/histFileMod.F90
index 6e89d15ff192..c11eafe96f45 100644
--- a/components/elm/src/main/histFileMod.F90
+++ b/components/elm/src/main/histFileMod.F90
@@ -28,12 +28,13 @@ module histFileMod
use FatesInterfaceTypesMod , only : nlevheight_fates => nlevheight
use FatesInterfaceTypesMod , only : nlevdamage_fates => nlevdamage
use FatesInterfaceTypesMod , only : nlevcoage
- use FatesLitterMod , only : nfsc_fates => nfsc
- use FatesLitterMod , only : ncwd_fates => ncwd
+ use FatesLitterMod , only : nfsc_fates => nfsc
+ use FatesConstantsMod , only : n_landuse_cats
+ use FatesLitterMod , only : ncwd_fates => ncwd
use FatesInterfaceTypesMod , only : numpft_fates => numpft
use PRTGenericMod , only : nelements_fates => num_elements
- use TopounitType , only : top_pp
- use topounit_varcon , only: max_topounits, has_topounit
+ use TopounitType , only : top_pp
+ use topounit_varcon , only: max_topounits, has_topounit
!
implicit none
@@ -1951,6 +1952,8 @@ subroutine htape_create (t, histrest)
call ncd_defdim(lnfid, 'fates_levelcwd', nelements_fates * ncwd_fates, dimid)
call ncd_defdim(lnfid, 'fates_levelage', nelements_fates * nlevage_fates, dimid)
call ncd_defdim(lnfid, 'fates_levagefuel', nlevage_fates * nfsc_fates, dimid)
+ call ncd_defdim(lnfid, 'fates_levlanduse', n_landuse_cats, dimid)
+ call ncd_defdim(lnfid, 'fates_levlulu', n_landuse_cats * n_landuse_cats, dimid)
end if
if ( .not. lhistrest )then
@@ -2353,6 +2356,7 @@ subroutine htape_timeconst(t, mode)
use FatesInterfaceTypesMod, only : fates_hdim_camap_levcapf
use FatesInterfaceTypesMod, only : fates_hdim_levage
use FatesInterfaceTypesMod, only : fates_hdim_levpft
+ use FatesInterfaceTypesMod, only : fates_hdim_levlanduse
use FatesInterfaceTypesMod, only : fates_hdim_scmap_levscag
use FatesInterfaceTypesMod, only : fates_hdim_agmap_levscag
use FatesInterfaceTypesMod, only : fates_hdim_levfuel
@@ -2463,6 +2467,8 @@ subroutine htape_timeconst(t, mode)
long_name='FATES patch age (yr)', ncid=nfid(t))
call ncd_defvar(varname='fates_levpft',xtype=ncd_int, dim1name='fates_levpft', &
long_name='FATES pft number', ncid=nfid(t))
+ call ncd_defvar(varname='fates_levlanduse',xtype=ncd_int, dim1name='fates_levlanduse', &
+ long_name='FATES land use label', ncid=nfid(t))
call ncd_defvar(varname='fates_levfuel',xtype=ncd_int, dim1name='fates_levfuel', &
long_name='FATES fuel index', ncid=nfid(t))
call ncd_defvar(varname='fates_levcwdsc',xtype=ncd_int, dim1name='fates_levcwdsc', &
@@ -2548,6 +2554,7 @@ subroutine htape_timeconst(t, mode)
call ncd_io(varname='fates_scmap_levscpf',data=fates_hdim_scmap_levscpf, ncid=nfid(t), flag='write')
call ncd_io(varname='fates_levage',data=fates_hdim_levage, ncid=nfid(t), flag='write')
call ncd_io(varname='fates_levpft',data=fates_hdim_levpft, ncid=nfid(t), flag='write')
+ call ncd_io(varname='fates_levlanduse',data=fates_hdim_levlanduse, ncid=nfid(t), flag='write')
call ncd_io(varname='fates_levfuel',data=fates_hdim_levfuel, ncid=nfid(t), flag='write')
call ncd_io(varname='fates_levcwdsc',data=fates_hdim_levcwdsc, ncid=nfid(t), flag='write')
call ncd_io(varname='fates_levcan',data=fates_hdim_levcan, ncid=nfid(t), flag='write')
@@ -4828,6 +4835,10 @@ subroutine hist_addfld2d (fname, type2d, units, avgflag, long_name, type1d_out,
num2d = nlevcoage*numpft_fates
case ('fates_levpft')
num2d = numpft_fates
+ case ('fates_levlanduse')
+ num2d = n_landuse_cats
+ case ('fates_levlulu')
+ num2d = n_landuse_cats * n_landuse_cats
case ('fates_levage')
num2d = nlevage_fates
case ('fates_levfuel')