diff --git a/Externals_CLM.cfg b/Externals_CLM.cfg index 5f8e8d2441..dc1bc3f0e7 100644 --- a/Externals_CLM.cfg +++ b/Externals_CLM.cfg @@ -2,7 +2,7 @@ local_path = src/fates protocol = git repo_url = https://github.com/NGEET/fates -tag = sci.1.68.2_api.31.0.0 +tag = sci.1.70.0_api.32.0.0 required = True [externals_description] diff --git a/bld/CLMBuildNamelist.pm b/bld/CLMBuildNamelist.pm index 17d64cd59f..4df42d5e74 100755 --- a/bld/CLMBuildNamelist.pm +++ b/bld/CLMBuildNamelist.pm @@ -784,7 +784,7 @@ sub setup_cmdl_fates_mode { my @list = ( "fates_spitfire_mode", "use_fates_planthydro", "use_fates_ed_st3", "use_fates_ed_prescribed_phys", "use_fates_cohort_age_tracking","use_fates_inventory_init","use_fates_fixed_biogeog", "use_fates_nocomp","use_fates_sp","fates_inventory_ctrl_filename","use_fates_logging", - "fates_parteh_mode","use_fates_tree_damage","fates_seeddisp_cadence" ); + "fates_parteh_mode","use_fates_tree_damage","fates_seeddisp_cadence","use_fates_luh","fluh_timeseries" ); # dis-allow fates specific namelist items with non-fates runs foreach my $var ( @list ) { if ( defined($nl->get_value($var)) ) { @@ -4370,7 +4370,7 @@ sub setup_logic_fates { add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'fates_paramfile', 'phys'=>$nl_flags->{'phys'}); my @list = ( "fates_spitfire_mode", "use_fates_planthydro", "use_fates_ed_st3", "use_fates_ed_prescribed_phys", "use_fates_inventory_init","use_fates_fixed_biogeog","use_fates_nocomp","fates_seeddisp_cadence", - "use_fates_logging","fates_parteh_mode", "use_fates_cohort_age_tracking","use_fates_tree_damage" ); + "use_fates_logging","fates_parteh_mode", "use_fates_cohort_age_tracking","use_fates_tree_damage","use_fates_luh" ); foreach my $var ( @list ) { add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, 'use_fates'=>$nl_flags->{'use_fates'}, 'use_fates_sp'=>$nl_flags->{'use_fates_sp'} ); @@ -4398,14 +4398,14 @@ sub setup_logic_fates { # spit-fire can't be on with FATES SP mode is active if ( $nl->get_value('fates_spitfire_mode') > 0 ) { $log->fatal_error('fates_spitfire_mode can NOT be set to greater than 0 when use_fates_sp is true'); + } } - } } my $var = "use_fates_inventory_init"; if ( defined($nl->get_value($var)) ) { if ( &value_is_true($nl->get_value($var)) ) { $var = "fates_inventory_ctrl_filename"; - my $fname = substr $nl->get_value($var), 1, -1; # ignore first and last positions of string because those are quote characters + my $fname = remove_leading_and_trailing_quotes( $nl->get_value($var) ); if ( ! defined($nl->get_value($var)) ) { $log->fatal_error("$var is required when use_fates_inventory_init is set" ); } elsif ( ! -f "$fname" ) { @@ -4413,6 +4413,19 @@ sub setup_logic_fates { } } } + my $var = "use_fates_luh"; + if ( defined($nl->get_value($var)) ) { + if ( &value_is_true($nl->get_value($var)) ) { + $var = "fluh_timeseries"; + add_default($opts, $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)) ) { + $log->fatal_error("$var is required when use_fates_luh is set" ); + } elsif ( ! -f "$fname" ) { + $log->fatal_error("$fname does NOT point to a valid filename" ); + } + } + } } } diff --git a/bld/namelist_files/namelist_defaults_ctsm.xml b/bld/namelist_files/namelist_defaults_ctsm.xml index 3997066a0b..7891361238 100644 --- a/bld/namelist_files/namelist_defaults_ctsm.xml +++ b/bld/namelist_files/namelist_defaults_ctsm.xml @@ -492,7 +492,7 @@ attributes from the config_cache.xml file (with keys converted to upper-case). -lnd/clm2/paramdata/fates_params_api.25.5.0_12pft_c230628.nc +lnd/clm2/paramdata/fates_params_api.32.0.0_12pft_c231215.nc @@ -1572,6 +1572,15 @@ use_crop=".true.">lnd/clm2/surfdata_map/ctsm5.1.dev052/landuse.timeseries_mpasa1 lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP5-3.4_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.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 + .true. .true. @@ -2755,6 +2764,7 @@ use_crop=".true.">lnd/clm2/surfdata_map/ctsm5.1.dev052/landuse.timeseries_mpasa1 .false. .false. .false. +.false. 1 0 diff --git a/bld/namelist_files/namelist_definition_ctsm.xml b/bld/namelist_files/namelist_definition_ctsm.xml index 97310ebe80..b672b43125 100644 --- a/bld/namelist_files/namelist_definition_ctsm.xml +++ b/bld/namelist_files/namelist_definition_ctsm.xml @@ -777,6 +777,22 @@ Full pathname to the inventory initialization control file. (Only relevant if FATES is on). + + +If TRUE, enable use of land use harmonization (LUH) state and transition data from luh_timeseries file. +(Also, only valid for use_fates = true and is incompatible with transient runs currently.) + + + + +Full pathname of unified land use harmonization (LUH) data file. This causes the land-use +types to vary over time. +(Required, if use_fates_luh=T) +(Only relevant if FATES is on). + + Toggle to turn on the LUNA model, to effect Photosynthesis by leaf Nitrogen diff --git a/bld/unit_testers/build-namelist_test.pl b/bld/unit_testers/build-namelist_test.pl index 4d03124116..9b579dd9ce 100755 --- a/bld/unit_testers/build-namelist_test.pl +++ b/bld/unit_testers/build-namelist_test.pl @@ -1061,6 +1061,16 @@ sub cat_and_create_namelistinfile { GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, + "useinventorybutnotfile" =>{ options=>"--res 0.9x1.25 --bgc fates --envxml_dir . --no-megan", + namelst=>"use_fates_luh=.true.", + GLC_TWO_WAY_COUPLING=>"FALSE", + phys=>"clm4_5", + }, + "inventoryfileDNE" =>{ options=>"-bgc fates -envxml_dir . -no-megan", + namelst=>"use_fates_luh=.true., fluh_timeseries='zztop'", + GLC_TWO_WAY_COUPLING=>"FALSE", + phys=>"clm4_5", + }, "useMEGANwithFATES" =>{ options=>"-bgc fates -envxml_dir . -megan", namelst=>"", GLC_TWO_WAY_COUPLING=>"FALSE", diff --git a/cime_config/testdefs/testlist_clm.xml b/cime_config/testdefs/testlist_clm.xml index 5e15eba958..dec8cf49d8 100644 --- a/cime_config/testdefs/testlist_clm.xml +++ b/cime_config/testdefs/testlist_clm.xml @@ -2900,6 +2900,16 @@ + + + + + + + + + + diff --git a/cime_config/testdefs/testmods_dirs/clm/Fates/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/Fates/user_nl_clm index 03ed340cbb..406fb598f6 100644 --- a/cime_config/testdefs/testmods_dirs/clm/Fates/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/Fates/user_nl_clm @@ -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/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2/include_user_mods new file mode 100644 index 0000000000..14f7591b72 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2/include_user_mods @@ -0,0 +1 @@ +../FatesCold diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2/user_nl_clm new file mode 100644 index 0000000000..854c21407f --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2/user_nl_clm @@ -0,0 +1 @@ +use_fates_luh = .true. diff --git a/cime_config/usermods_dirs/fates_sp/user_nl_clm b/cime_config/usermods_dirs/fates_sp/user_nl_clm index 0df139403d..093ecd7eda 100644 --- a/cime_config/usermods_dirs/fates_sp/user_nl_clm +++ b/cime_config/usermods_dirs/fates_sp/user_nl_clm @@ -21,9 +21,8 @@ hist_fexcl1 = 'FATES_TRIMMING', 'FATES_COLD_STATUS', 'FATES_GDD', 'FATES_NCHILLD 'FATES_SEEDS_IN_EXTERN_EL', 'FATES_SEED_GERM_EL', 'FATES_SEED_DECAY_EL', 'FATES_STOREC', 'FATES_VEGC', 'FATES_SAPWOODC', '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_DISTURBANCE_RATE_LOGGING', 'FATES_DISTURBANCE_RATE_TREEFALL', - 'FATES_DISTURBANCE_RATE_POTENTIAL', 'FATES_HARVEST_CARBON_FLUX', 'FATES_GPP_CANOPY', 'FATES_AUTORESP_CANOPY', + 'FATES_HARVEST_CARBON_FLUX', 'FATES_GPP_CANOPY', 'FATES_AUTORESP_CANOPY', 'FATES_GPP_USTORY', 'FATES_AUTORESP_USTORY', 'FATES_CROWNAREA_CL', 'FATES_DEMOTION_CARBONFLUX', 'FATES_PROMOTION_CARBONFLUX', 'FATES_MORTALITY_CFLUX_CANOPY', 'FATES_MORTALITY_CFLUX_USTORY', 'FATES_DDBH_CANOPY_SZ', 'FATES_DDBH_USTORY_SZ', 'FATES_BASALAREA_SZ', diff --git a/doc/.ChangeLog_template b/doc/.ChangeLog_template index bbd65c8c83..a1170a61cf 100644 --- a/doc/.ChangeLog_template +++ b/doc/.ChangeLog_template @@ -27,8 +27,8 @@ Does this tag change answers significantly for any of the following physics conf [ ] clm4_5 -Bugs fixed or introduced ------------------------- +Bugs fixed +---------- [Remove any lines that don't apply. Remove entire section if nothing applies.] CTSM issues fixed (include CTSM Issue #): diff --git a/doc/ChangeLog b/doc/ChangeLog index 67564b6dd0..925141f310 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,4 +1,104 @@ =============================================================== +Tag name: ctsm5.1.dev160 +Originator(s): glemieux (Gregory Lemieux, LBNL, glemieux@lbl.gov) +Date: Sat 30 Dec 2023 11:23:47 PM MST +One-line Summary: FATES landuse version 1 + +Purpose and description of changes +---------------------------------- + +This tag enables FATES to utilize the state and transitions data +from the Land Use Harmonization (https://luh.umd.edu/) data sets. +This data has been preprocessed using tooling provided by FATES via +a separate pull request (FATES#1032). A new module has been added +to the dyn_subgrid directory that largely adapts the dynHarvest +module to import and read this minimially processed data, which is +data is passed to fates. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- +CTSM issues fixed (include CTSM Issue #): + #1077 -- Read in full LUH2 dataset for use by FATES + #2283 -- fates wood product flux not being correctly reported during CBalanceCheck endrun diagnostic output + +Notes of particular relevance for users +--------------------------------------- +Changes made to namelist defaults (e.g., changed parameter values): + New namelist item: fluh_timeseries and use_fates_luh + +Notes of particular relevance for developers: +--------------------------------------------- +Changes to tests or testing: + FATES landuse testmod, FatesColdLUH2, added + +IMPORTANT NOTE ON BASELINES: + FATES baseline tests have a change in namelists because the fluh_timeseries file is listed in the baselines + but was removed in a last minute change. Compare to baseline other than that change are exact though. + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - PASS (66 FATES tests differ because of new fates param file) + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- PASS + + fates tests: (give name of baseline if different from CTSM tagname, normally fates baselines are fates--) + derecho ----- OK + izumi ------- OK + + +Answer changes +-------------- + +Changes answers relative to baseline: yes, for FATES only + + Summarize any changes to answers, i.e., + - what code configurations: FATES + - what platforms/compilers: ALL + - nature of change (roundoff; larger than roundoff/same climate; new climate): larger than roundoff + + The fates tag update incorporates bug fixes and hydraulic mortality fixes, as well as the + restructured disturbance code necessary to accomodate the new landuse transitions capability. + As such, small differences were observed in testmods that engaged specific disturbance modes + or were long enough to trigger other default disturbances (e.g. fire) + +Other details +------------- + +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): + fates: sci.1.69.0_api.31.0.0 -> fates-sci.1.70.0_api.32.0.0 + +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/2076 + https://github.com/NGEET/fates/pull/1040 + +=============================================================== +=============================================================== Tag name: ctsm5.1.dev159 Originator(s): multiple (slevis (Sam Levis), afoster (Adrianna Foster), erik (Erik Kluzek), wwieder (Will Wieder), glemieux (Greg Lemieux), oleson (Keith Oleson), sacks (Bill Sacks), samrabin (Sam Rabin), santos (Sean Patrick Santos)) Date: Tue 12 Dec 2023 11:10:26 AM MST diff --git a/doc/ChangeSum b/doc/ChangeSum index 4b82850d85..d9da687477 100644 --- a/doc/ChangeSum +++ b/doc/ChangeSum @@ -1,5 +1,6 @@ Tag Who Date Summary ============================================================================================================================ + ctsm5.1.dev160 glemieux 12/30/2023 FATES landuse version 1 ctsm5.1.dev159 multiple 12/12/2023 Various BFB fixes and updates ctsm5.1.dev158 erik 12/07/2023 First tag with testing moved to Derecho and working PE-layouts for Derecho ctsm5.1.dev157 samrabin 12/05/2023 Update Externals to work on Derecho diff --git a/src/biogeochem/CNBalanceCheckMod.F90 b/src/biogeochem/CNBalanceCheckMod.F90 index 35efd2e9aa..8801efdf72 100644 --- a/src/biogeochem/CNBalanceCheckMod.F90 +++ b/src/biogeochem/CNBalanceCheckMod.F90 @@ -258,7 +258,6 @@ subroutine CBalanceCheck(this, bounds, num_soilc, filter_soilc, & real(r8) :: hrv_xsmrpool_amount_left_to_dribble(bounds%begg:bounds%endg) real(r8) :: gru_conv_cflux_amount_left_to_dribble(bounds%begg:bounds%endg) real(r8) :: dwt_conv_cflux_amount_left_to_dribble(bounds%begg:bounds%endg) - real(r8) :: fates_woodproduct_flux ! Total carbon wood products flux from FATES to CLM [gC/m2/s] !----------------------------------------------------------------------- @@ -309,11 +308,7 @@ subroutine CBalanceCheck(this, bounds, num_soilc, filter_soilc, & s = clm_fates%f2hmap(ic)%hsites(c) - - fates_woodproduct_flux = clm_fates%fates(ic)%bc_out(s)%hrv_deadstemc_to_prod10c + & - clm_fates%fates(ic)%bc_out(s)%hrv_deadstemc_to_prod100c - - col_cinputs = fates_litter_flux(c) + fates_woodproduct_flux + col_cinputs = fates_litter_flux(c) ! calculate total column-level outputs ! fates has already exported burn losses and fluxes to the atm @@ -372,7 +367,6 @@ subroutine CBalanceCheck(this, bounds, num_soilc, filter_soilc, & write(iulog,*)'--- Inputs ---' if( col%is_fates(c) ) then write(iulog,*)'fates litter_flux = ',fates_litter_flux(c)*dt - write(iulog,*)'fates wood product flux = ',fates_woodproduct_flux*dt else write(iulog,*)'gpp = ',gpp(c)*dt end if diff --git a/src/dyn_subgrid/dynFATESLandUseChangeMod.F90 b/src/dyn_subgrid/dynFATESLandUseChangeMod.F90 new file mode 100644 index 0000000000..45f4340d6a --- /dev/null +++ b/src/dyn_subgrid/dynFATESLandUseChangeMod.F90 @@ -0,0 +1,208 @@ +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 clm_varcon , only : grlnd + use clm_varctl , only : iulog + + implicit none + + private + + ! Yearly landuse transition rate (fraction of gridcell), landuse transition name x gridcell + real(r8), allocatable, public :: landuse_transitions(:,:) + + ! Landuse state at beginning of year (fraction of gridcell), landuse state name x gridcell + real(r8), allocatable, public :: landuse_states(:,:) + + ! Number of landuse transition and state names + integer, public, parameter :: num_landuse_transition_vars = 108 + integer, public, parameter :: num_landuse_state_vars = 12 + + ! landuse filename + 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','primn','secdf','secdn','pastr','range', & + 'urban','c3ann','c4ann','c3per','c4per','c3nfx'] + + 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 clm_varctl , only : use_cn, 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') + + if (use_cn) return ! Use this as a protection in lieu of build namelist check? + + ! 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) + + + ! !DESCRIPTION: + ! Get landuse state and transition rate data + ! + ! Note that the landuse state and transition rates are stored as fractions + ! of a gridcell for a given year, which is constant throughout the year. + ! This routine does not interpolate the rate at this time; any interpolation + ! is handled by FATES. + + ! !USES: + use dynTimeInfoMod , only : time_info_type + use clm_varctl , only : use_cn + + ! !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 ! variable number index + logical :: init_flag ! local variable to take optional argument value + real(r8), allocatable :: this_data(:) ! temporary array to take get_current_date results + + character(len=*), parameter :: subname = 'dynFatesLandUseInterp' + !----------------------------------------------------------------------- + SHR_ASSERT_ALL(bounds%level == BOUNDS_LEVEL_PROC, subname // ': argument must be PROC-level bounds') + + ! Determine if the optional initialization state flag is present and if so + ! set the init_flag to that optional input value + init_flag = .false. + if (present(init_state)) then + init_flag = init_state + end if + + ! Get the current year + call dynFatesLandUse_file%time_info%set_current_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 + else + ! Loop through all variables on the data file and put data into the temporary array + ! then update the global state and transitions array. + 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/src/dyn_subgrid/dynSubgridDriverMod.F90 b/src/dyn_subgrid/dynSubgridDriverMod.F90 index dada3e9975..e5ca3f002e 100644 --- a/src/dyn_subgrid/dynSubgridDriverMod.F90 +++ b/src/dyn_subgrid/dynSubgridDriverMod.F90 @@ -201,10 +201,11 @@ subroutine dynSubgrid_driver(bounds_proc, ! OUTSIDE any loops over clumps in the driver. ! ! !USES: - use clm_varctl , only : use_cn, use_fates - use dynInitColumnsMod , only : initialize_new_columns - use dynConsBiogeophysMod , only : dyn_hwcontent_init, dyn_hwcontent_final - use dynEDMod , only : dyn_ED + use clm_varctl , only : use_cn, use_fates, use_fates_luh + use dynInitColumnsMod , only : initialize_new_columns + use dynConsBiogeophysMod , only : dyn_hwcontent_init, dyn_hwcontent_final + use dynEDMod , only : dyn_ED + use dynFATESLandUseChangeMod, only : dynFatesLandUseInterp ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds_proc ! processor-level bounds @@ -288,6 +289,11 @@ subroutine dynSubgrid_driver(bounds_proc, if (get_do_transient_urban()) then call dynurban_interp(bounds_proc) end if + + if (use_fates_luh) then + call dynFatesLandUseInterp(bounds_proc) + end if + ! ========================================================================== ! Do land cover change that does not require I/O ! ========================================================================== diff --git a/src/main/clm_initializeMod.F90 b/src/main/clm_initializeMod.F90 index 077a25b796..3354c1e7d0 100644 --- a/src/main/clm_initializeMod.F90 +++ b/src/main/clm_initializeMod.F90 @@ -133,7 +133,7 @@ subroutine initialize2(ni,nj) use clm_varpar , only : natpft_size,cft_size use clm_varctl , only : fsurdat use clm_varctl , only : finidat, finidat_interp_source, finidat_interp_dest, fsurdat - use clm_varctl , only : use_cn, use_fates + use clm_varctl , only : use_cn, use_fates, use_fates_luh use clm_varctl , only : use_crop, ndep_from_cpl, fates_spitfire_mode use clm_varorb , only : eccen, mvelpp, lambm0, obliqr use clm_varctl , only : use_cropcal_streams @@ -142,7 +142,7 @@ subroutine initialize2(ni,nj) use decompInitMod , only : decompInit_clumps, decompInit_glcp use domainMod , only : domain_check, ldomain, domain_init use surfrdMod , only : surfrd_get_data - use controlMod , only : NLFilename + use controlMod , only : NLFilename, fluh_timeseries use initGridCellsMod , only : initGridCells use ch4varcon , only : ch4conrd use UrbanParamsType , only : UrbanInput, IsSimpleBuildTemp @@ -175,6 +175,7 @@ subroutine initialize2(ni,nj) use CNSharedParamsMod , only : CNParamsSetSoilDepth use NutrientCompetitionFactoryMod , only : create_nutrient_competition_method use FATESFireFactoryMod , only : scalar_lightning + use dynFATESLandUseChangeMod , only : dynFatesLandUseInit ! ! !ARGUMENTS integer, intent(in) :: ni, nj ! global grid sizes @@ -406,6 +407,11 @@ subroutine initialize2(ni,nj) call dynSubgrid_init(bounds_proc, glc_behavior, crop_inst) call t_stopf('init_dyn_subgrid') + ! Initialize fates LUH2 usage + if (use_fates_luh) then + call dynFatesLandUseInit(bounds_proc, fluh_timeseries) + end if + ! Initialize baseline water and energy states needed for dynamic subgrid operation ! This will be overwritten by the restart file, but needs to be done for a cold start ! case. diff --git a/src/main/clm_varctl.F90 b/src/main/clm_varctl.F90 index 6e89f0952e..e0d142bffd 100644 --- a/src/main/clm_varctl.F90 +++ b/src/main/clm_varctl.F90 @@ -310,6 +310,8 @@ module clm_varctl logical, public :: use_fates_inventory_init = .false. ! true => initialize fates from inventory logical, public :: use_fates_fixed_biogeog = .false. ! true => use fixed biogeography mode logical, public :: use_fates_nocomp = .false. ! true => use no comopetition mode + logical, public :: use_fates_luh = .false. ! true => use FATES landuse data mode + character(len=256), public :: fluh_timeseries = '' ! filename for fates landuse timeseries data character(len=256), public :: fates_inventory_ctrl_filename = '' ! filename for inventory control ! FATES SP AND FATES BGC are MUTUTALLY EXCLUSIVE, THEY CAN'T BOTH BE ON diff --git a/src/main/controlMod.F90 b/src/main/controlMod.F90 index deb8c044d8..44efec4eeb 100644 --- a/src/main/controlMod.F90 +++ b/src/main/controlMod.F90 @@ -230,6 +230,8 @@ subroutine control_init(dtime) use_fates_fixed_biogeog, & use_fates_nocomp, & use_fates_sp, & + use_fates_luh, & + fluh_timeseries, & fates_inventory_ctrl_filename, & fates_parteh_mode, & fates_seeddisp_cadence, & @@ -780,9 +782,11 @@ 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_bgc, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (fates_inventory_ctrl_filename, len(fates_inventory_ctrl_filename), MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (fates_paramfile, len(fates_paramfile) , MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (fluh_timeseries, len(fates_paramfile) , MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (fates_parteh_mode, 1, MPI_INTEGER, 0, mpicom, ier) call mpi_bcast (fates_seeddisp_cadence, 1, MPI_INTEGER, 0, mpicom, ier) @@ -1152,9 +1156,11 @@ 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, *) ' fluh_timeseries = ', trim(fluh_timeseries) write(iulog, *) ' fates_seeddisp_cadence = ', fates_seeddisp_cadence write(iulog, *) ' fates_seeddisp_cadence: 0, 1, 2, 3 => off, daily, monthly, or yearly dispersal' - write(iulog, *) ' fates_inventory_ctrl_filename = ',fates_inventory_ctrl_filename + write(iulog, *) ' fates_inventory_ctrl_filename = ', trim(fates_inventory_ctrl_filename) end if end subroutine control_print diff --git a/src/main/histFileMod.F90 b/src/main/histFileMod.F90 index c72117b090..fb1a25db37 100644 --- a/src/main/histFileMod.F90 +++ b/src/main/histFileMod.F90 @@ -27,9 +27,10 @@ module histFileMod use FatesInterfaceTypesMod , only : nlevsclass, nlevage, nlevcoage use FatesInterfaceTypesMod , only : nlevheight use FatesInterfaceTypesMod , only : nlevdamage - use FatesLitterMod , only : nfsc - use FatesLitterMod , only : ncwd - use PRTGenericMod , only : num_elements_fates => num_elements + use FatesConstantsMod , only : n_landuse_cats + use FatesLitterMod , only : nfsc + use FatesLitterMod , only : ncwd + use PRTGenericMod , only : num_elements_fates => num_elements use FatesInterfaceTypesMod , only : numpft_fates => numpft use ncdio_pio @@ -2513,6 +2514,8 @@ subroutine htape_create (t, histrest) call ncd_defdim(lnfid, 'fates_levelage', num_elements_fates * nlevage, dimid) call ncd_defdim(lnfid, 'fates_levagefuel', nlevage * nfsc, dimid) call ncd_defdim(lnfid, 'fates_levclscpf', nclmax*nlevsclass*numpft_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 @@ -3065,6 +3068,7 @@ subroutine htape_timeconst(t, mode) use FatesInterfaceTypesMod, only : fates_hdim_scmap_levcdpf use FatesInterfaceTypesMod, only : fates_hdim_cdmap_levcdpf use FatesInterfaceTypesMod, only : fates_hdim_pftmap_levcdpf + use FatesInterfaceTypesMod, only : fates_hdim_levlanduse ! @@ -3193,6 +3197,8 @@ subroutine htape_timeconst(t, mode) long_name='FATES pft index of the combined damage-size-PFT dimension', ncid=nfid(t)) call ncd_defvar(varname='fates_levcdam', xtype=tape(t)%ncprec, dim1name='fates_levcdam', & long_name='FATES damage class lower bound', units='unitless', ncid=nfid(t)) + call ncd_defvar(varname='fates_levlanduse',xtype=ncd_int, dim1name='fates_levlanduse', & + long_name='FATES land use label', ncid=nfid(t)) end if @@ -3242,6 +3248,7 @@ subroutine htape_timeconst(t, mode) call ncd_io(varname='fates_scmap_levcdpf',data=fates_hdim_scmap_levcdpf, ncid=nfid(t), flag='write') call ncd_io(varname='fates_cdmap_levcdpf',data=fates_hdim_cdmap_levcdpf, ncid=nfid(t), flag='write') call ncd_io(varname='fates_pftmap_levcdpf',data=fates_hdim_pftmap_levcdpf, ncid=nfid(t), flag='write') + call ncd_io(varname='fates_levlanduse',data=fates_hdim_levlanduse, ncid=nfid(t), flag='write') end if endif @@ -5557,6 +5564,10 @@ subroutine hist_addfld2d (fname, type2d, units, avgflag, long_name, type1d_out, num2d = nlevage*nfsc case('fates_levclscpf') num2d = nclmax * nclmax * numpft_fates + case ('fates_levlanduse') + num2d = n_landuse_cats + case ('fates_levlulu') + num2d = n_landuse_cats * n_landuse_cats case('cft') if (cft_size > 0) then num2d = cft_size diff --git a/src/main/surfrdMod.F90 b/src/main/surfrdMod.F90 index 78c9d8492e..23e96e7c1a 100644 --- a/src/main/surfrdMod.F90 +++ b/src/main/surfrdMod.F90 @@ -723,6 +723,7 @@ subroutine surfrd_veg_all(begg, endg, ncid, ns, actual_numcft) ! !USES: use clm_varctl , only : create_crop_landunit, use_fates, n_dom_pfts use clm_varpar , only : natpft_lb, natpft_ub, natpft_size, cft_size, cft_lb, cft_ub + use clm_varpar , only : surfpft_lb, surfpft_ub use clm_instur , only : wt_lunit, wt_nat_patch, wt_cft, fert_cft use landunit_varcon , only : istsoil, istcrop use surfrdUtilsMod , only : convert_cft_to_pft @@ -851,7 +852,7 @@ subroutine surfrd_veg_all(begg, endg, ncid, ns, actual_numcft) ! - Pfts could be up to 16 before collapsing if create_crop_landunit = .F. ! TODO Add the same call to subroutine dynpft_interp for transient runs - call collapse_to_dominant(wt_nat_patch(begg:endg,:), natpft_lb, natpft_ub, & + call collapse_to_dominant(wt_nat_patch(begg:endg,:), surfpft_lb, surfpft_ub, & begg, endg, n_dom_pfts) end subroutine surfrd_veg_all diff --git a/src/utils/clmfates_interfaceMod.F90 b/src/utils/clmfates_interfaceMod.F90 index 48dc3297c0..83d7186021 100644 --- a/src/utils/clmfates_interfaceMod.F90 +++ b/src/utils/clmfates_interfaceMod.F90 @@ -59,6 +59,7 @@ module CLMFatesInterfaceMod use clm_varctl , only : use_fates_fixed_biogeog use clm_varctl , only : use_fates_nocomp use clm_varctl , only : use_fates_sp + use clm_varctl , only : use_fates_luh use clm_varctl , only : fates_seeddisp_cadence use clm_varctl , only : fates_inventory_ctrl_filename use clm_varctl , only : use_nitrif_denitrif @@ -140,6 +141,7 @@ module CLMFatesInterfaceMod use PRTGenericMod , only : num_elements use FatesInterfaceTypesMod, only : hlm_stepsize use FatesInterfaceTypesMod, only : fates_maxPatchesPerSite + use FatesInterfaceTypesMod, only : hlm_num_luh2_states use FatesInterfaceTypesMod, only : fates_dispersal_cadence_none use EDMainMod , only : ed_ecosystem_dynamics use EDMainMod , only : ed_update_site @@ -173,6 +175,12 @@ module CLMFatesInterfaceMod use FatesDispersalMod , only : lneighbors, dispersal_type, IsItDispersalTime use perf_mod , only : t_startf, t_stopf + + 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 + implicit none type, public :: f2hmap_type @@ -375,6 +383,9 @@ subroutine CLMFatesGlobals2() integer :: pass_is_restart integer :: pass_cohort_age_tracking integer :: pass_tree_damage + integer :: pass_use_luh + integer :: pass_num_luh_states + integer :: pass_num_luh_transitions call t_startf('fates_globals2') @@ -514,6 +525,19 @@ subroutine CLMFatesGlobals2() 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 + 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_inventory_init) then pass_inventory_init = 1 else @@ -730,7 +754,9 @@ subroutine init(this, bounds_proc ) ndecomp = col%nbedrock(c) - call allocate_bcin(this%fates(nc)%bc_in(s),col%nbedrock(c),ndecomp, num_harvest_inst,surfpft_lb,surfpft_ub) + call allocate_bcin(this%fates(nc)%bc_in(s),col%nbedrock(c),ndecomp, & + num_harvest_inst, num_landuse_state_vars, num_landuse_transition_vars, & + surfpft_lb,surfpft_ub) call allocate_bcout(this%fates(nc)%bc_out(s),col%nbedrock(c),ndecomp) call zero_bcs(this%fates(nc),s) @@ -1054,10 +1080,15 @@ subroutine dynamics_driv(this, nc, bounds_clump, & write(iulog,*) harvest_units call endrun(msg=errMsg(sourcefile, __LINE__)) end if - - endif + 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 @@ -1901,9 +1932,9 @@ subroutine init_coldstart(this, waterstatebulk_inst, waterdiagnosticbulk_inst, & real(r8) :: vol_ice real(r8) :: eff_porosity integer :: nlevsoil ! Number of soil layers at each site - integer :: j + integer :: i, j integer :: s - integer :: c + integer :: c, g integer :: p ! HLM patch index integer :: ft ! plant functional type @@ -1993,6 +2024,18 @@ subroutine init_coldstart(this, waterstatebulk_inst, waterdiagnosticbulk_inst, & 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%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 + ! Newly initialized patches need a starting temperature call init_patches(this%fates(nc)%nsites, this%fates(nc)%sites, & this%fates(nc)%bc_in) @@ -3077,6 +3120,7 @@ subroutine init_history_io(this,bounds_proc) use FatesIOVariableKindMod, only : site_height_r8, site_elem_r8, site_elpft_r8 use FatesIOVariableKindMod, only : site_elcwd_r8, site_elage_r8, site_agefuel_r8 use FatesIOVariableKindMod, only : site_cdpf_r8, site_cdsc_r8, site_clscpf_r8 + use FatesIOVariableKindMod, only : site_landuse_r8, site_lulu_r8 use FatesIODimensionsMod, only : fates_bounds_type @@ -3179,7 +3223,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_agefuel_r8, & - site_cdsc_r8, site_cdpf_r8) + site_cdsc_r8, site_cdpf_r8, & + site_landuse_r8, site_lulu_r8) d_index = fates_hist%dim_kinds(dk_index)%dim2_index @@ -3442,7 +3487,8 @@ subroutine hlm_bounds_to_fates_bounds(hlm, fates) use FatesLitterMod, only : ncwd use EDParamsMod, only : nlevleaf, nclmax use FatesInterfaceTypesMod, only : numpft_fates => numpft - + use FatesConstantsMod, only : n_landuse_cats + type(bounds_type), intent(in) :: hlm type(fates_bounds_type), intent(out) :: fates @@ -3529,7 +3575,12 @@ subroutine hlm_bounds_to_fates_bounds(hlm, fates) fates%clscpf_begin = 1 fates%clscpf_end = numpft_fates * nlevsclass * nclmax - + + fates%landuse_begin = 1 + fates%landuse_end = n_landuse_cats + + fates%lulu_begin = 1 + fates%lulu_end = n_landuse_cats * n_landuse_cats call t_stopf('fates_hlm2fatesbnds')