diff --git a/bld/CLMBuildNamelist.pm b/bld/CLMBuildNamelist.pm index 997b9ccf94..acdad5c5cc 100755 --- a/bld/CLMBuildNamelist.pm +++ b/bld/CLMBuildNamelist.pm @@ -4640,23 +4640,37 @@ sub setup_logic_fates { if ( ! &value_is_true($nl->get_value('use_fates_luh')) ) { $log->fatal_error("use_fates_luh must be true when $var is true" ); } - if ( $nl->get_value('fates_harvest_mode') > 0) { - $log->fatal_error("fates_harvest_mode must be off (i.e. set to zero) when $var is true" ); + my $var = remove_leading_and_trailing_quotes($nl->get_value('fates_harvest_mode')); + if ( $var ne 'no_harvest') { + $log->fatal_error("fates_harvest_mode set to $var. It must set to no_harvest when use_potential_veg is true." ); } my $var = "fluh_timeseries"; if ( defined($nl->get_value($var)) ) { $log->fatal_error("fluh_timeseries can not be defined 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 - if ( $nl->get_value($var) > 2) { + 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')) ) { - $log->fatal_error("use_fates_luh is required to be true when $var is greater than 2" ); + $log->fatal_error("use_fates_luh is required to be true when $var is luhdata_mass or luhdata_area" ); + } + } elsif ( $mode eq 'surfdata_file' ) { + # 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)) ) { + $log->fatal_error("$var is required when fates_harvest_mode is surfdata_file" ); + } elsif ( ! -f "$fname" ) { + $log->fatal_error("$var 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 fdfeba7719..fe34e9f4b8 100644 --- a/bld/namelist_files/namelist_defaults_ctsm.xml +++ b/bld/namelist_files/namelist_defaults_ctsm.xml @@ -2015,7 +2015,7 @@ lnd/clm2/surfdata_esmf/NEON/surfdata_1x1_NEON_TOOL_hist_78pfts_CMIP6_simyr2000_c 0 -0 +no_harvest .false. .false. .false. @@ -2025,8 +2025,8 @@ lnd/clm2/surfdata_esmf/NEON/surfdata_1x1_NEON_TOOL_hist_78pfts_CMIP6_simyr2000_c .false. .false. .false. -.true. -.true. +.true. +.true. .true. .true. .false. diff --git a/bld/namelist_files/namelist_definition_ctsm.xml b/bld/namelist_files/namelist_definition_ctsm.xml index 1578b808b2..c12cb75ab6 100644 --- a/bld/namelist_files/namelist_definition_ctsm.xml +++ b/bld/namelist_files/namelist_definition_ctsm.xml @@ -734,15 +734,15 @@ Toggle to turn on no competition mode (only relevant if FATES is being used). Toggle to turn on FATES satellite phenology mode (only relevant if FATES is being used). - -Set FATES harvesting mode by setting fates_harvest_mode > 0. + +Set FATES harvesting mode by setting fates_harvest_mode to a valid string option. Allowed values are: - 0 : no fates harvesting of any kind - 1 : fates logging via fates logging event codes (see fates parameter file) only - 2 : fates harvest driven by CLM landuse timeseries data (dynHarvestMod) - 3 : fates harvest driven by LUH2 raw harvest data, area-based (dynFATESLandUseChangeMod) - 4 : fates harvest driven by LUH2 raw harvest data, mass-based (dynFATESLandUseChangeMod) + no_harvest: no fates harvesting of any kind + event_code: fates logging via fates logging event codes (see fates parameter file) only + surfdata_file: fates harvest driven by CLM 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) If TRUE, enable use of land use harmonization (LUH) state and transition data from luh_timeseries file. -This is enabled by default if fates_harvest_mode is set to use the raw LUH2 harvest -data (fates_harvest_mode >= 3) +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.) diff --git a/bld/unit_testers/build-namelist_test.pl b/bld/unit_testers/build-namelist_test.pl index 143d536624..59d69159f2 100755 --- a/bld/unit_testers/build-namelist_test.pl +++ b/bld/unit_testers/build-namelist_test.pl @@ -1035,7 +1035,7 @@ sub cat_and_create_namelistinfile { phys=>"clm5_0", }, "useloggingButNOTFATES" =>{ options=>"-envxml_dir . -no-megan", - namelst=>"fates_harvest_mode=1", + namelst=>"fates_harvest_mode=event_code", GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, @@ -1090,12 +1090,12 @@ sub cat_and_create_namelistinfile { phys=>"clm5_0", }, "useFATESPOTVEGwithHARVEST" =>{ options=>"-bgc fates -envxml_dir . -no-megan", - namelst=>"use_fates_potentialveg=T,fates_harvest_mode=1", + namelst=>"use_fates_potentialveg=T,fates_harvest_mode=event_code", GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "useFATESHARVEST3WOLUH" =>{ options=>"-bgc fates -envxml_dir . -no-megan", - namelst=>"use_fates_luh=F,fates_harvest_mode=3", + namelst=>"use_fates_luh=F,fates_harvest_mode=luhdata_area", GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2Mode0/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2Mode0/user_nl_clm index 929a8e6e14..b3b338e232 100644 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2Mode0/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2Mode0/user_nl_clm @@ -1 +1 @@ -fates_harvest_mode = 0 +fates_harvest_mode = no_harvest diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2Mode1/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2Mode1/user_nl_clm index dea75b71e7..c0e1c476be 100644 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2Mode1/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2Mode1/user_nl_clm @@ -1 +1 @@ -fates_harvest_mode = 1 +fates_harvest_mode = event_code diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2Mode2/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2Mode2/user_nl_clm index fd4c74fe57..61e1daaa93 100644 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2Mode2/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2Mode2/user_nl_clm @@ -1 +1 @@ -fates_harvest_mode = 2 +fates_harvest_mode = surfdata_file diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2Mode3/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2Mode3/user_nl_clm index 3332e9e526..d760105e68 100644 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2Mode3/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2Mode3/user_nl_clm @@ -1 +1 @@ -fates_harvest_mode = 3 +fates_harvest_mode = luhdata_area diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2Mode4/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2Mode4/user_nl_clm index 13dae9efee..bb5f30f75d 100644 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2Mode4/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2Mode4/user_nl_clm @@ -1 +1 @@ -fates_harvest_mode = 4 +fates_harvest_mode = luhdata_mass diff --git a/src/dyn_subgrid/dynFATESLandUseChangeMod.F90 b/src/dyn_subgrid/dynFATESLandUseChangeMod.F90 index 4f326d82a5..f330ee2b78 100644 --- a/src/dyn_subgrid/dynFATESLandUseChangeMod.F90 +++ b/src/dyn_subgrid/dynFATESLandUseChangeMod.F90 @@ -35,11 +35,11 @@ module dynFATESLandUseChangeMod integer, public, parameter :: num_landuse_harvest_vars = 5 ! Define the fates landuse namelist mode switch values - integer, public, parameter :: fates_harvest_no_logging = 0 - integer, public, parameter :: fates_harvest_logging_only = 1 - integer, public, parameter :: fates_harvest_clmlanduse = 2 - integer, public, parameter :: fates_harvest_luh_area = 3 - integer, public, parameter :: fates_harvest_luh_mass = 4 + character(len=13), public, parameter :: fates_harvest_no_logging = 'no_harvest' + character(len=13), public, parameter :: fates_harvest_logging_only = 'event_code' + character(len=13), public, parameter :: fates_harvest_clmlanduse = 'surfdata_file' + character(len=13), public, parameter :: fates_harvest_luh_area = 'luhdata_area' + character(len=13), public, parameter :: fates_harvest_luh_mass = 'luhdata_mass' ! Define landuse harvest unit integer representation integer, public, parameter :: landuse_harvest_area_units = 1 @@ -171,13 +171,14 @@ subroutine dynFatesLandUseInit(bounds, landuse_filename) end do ! Get the harvest rate data from the fates luh2 timeseries dataset if enabled - if (fates_harvest_mode .ge. fates_harvest_luh_area ) then + 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 (fates_harvest_mode .eq. fates_harvest_luh_area ) then + 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 (fates_harvest_mode .eq. fates_harvest_luh_mass ) then + 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 @@ -256,7 +257,8 @@ 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 (fates_harvest_mode .ge. fates_harvest_luh_area ) then + 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) diff --git a/src/dyn_subgrid/dynSubgridDriverMod.F90 b/src/dyn_subgrid/dynSubgridDriverMod.F90 index 162247a0ff..faef029b40 100644 --- a/src/dyn_subgrid/dynSubgridDriverMod.F90 +++ b/src/dyn_subgrid/dynSubgridDriverMod.F90 @@ -128,7 +128,7 @@ subroutine dynSubgrid_init(bounds_proc, glc_behavior, crop_inst) ! flanduse_timeseries file. However, this could theoretically be changed so that the ! harvest data were separated from the pftdyn data, allowing them to differ in the ! years over which they apply. - if (get_do_harvest() .or. fates_harvest_mode == fates_harvest_clmlanduse) then + if (get_do_harvest() .or. trim(fates_harvest_mode) == fates_harvest_clmlanduse) then call dynHarvest_init(bounds_proc, harvest_filename=get_flanduse_timeseries()) end if diff --git a/src/main/clm_varctl.F90 b/src/main/clm_varctl.F90 index c0fd45e4ee..7554288d30 100644 --- a/src/main/clm_varctl.F90 +++ b/src/main/clm_varctl.F90 @@ -321,7 +321,7 @@ module clm_varctl ! > 1 for external data (lightning and/or anthropogenic ignitions) ! see bld/namelist_files/namelist_definition_clm4_5.xml for details logical, public :: use_fates_tree_damage = .false. ! true => turn on tree damage module - integer, public :: fates_harvest_mode = 0 ! 0 for no harvest/logging; 1-4 for harvest mode options + character(len=256), public :: fates_harvest_mode = '' ! five different harvest modes; see namelist definition 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_ed_st3 = .false. ! true => static stand structure diff --git a/src/main/controlMod.F90 b/src/main/controlMod.F90 index 6703b1d99c..60b4a569fd 100644 --- a/src/main/controlMod.F90 +++ b/src/main/controlMod.F90 @@ -793,7 +793,7 @@ subroutine control_spmd() call mpi_bcast (for_testing_allow_interp_non_ciso_to_ciso, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (fates_spitfire_mode, 1, MPI_INTEGER, 0, mpicom, ier) - call mpi_bcast (fates_harvest_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 (use_fates_planthydro, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_fates_tree_damage, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_fates_cohort_age_tracking, 1, MPI_LOGICAL, 0, mpicom, ier) diff --git a/src/utils/clmfates_interfaceMod.F90 b/src/utils/clmfates_interfaceMod.F90 index f79f7387b9..43a574d6e3 100644 --- a/src/utils/clmfates_interfaceMod.F90 +++ b/src/utils/clmfates_interfaceMod.F90 @@ -187,6 +187,7 @@ module CLMFatesInterfaceMod use dynFATESLandUseChangeMod, only : fates_harvest_no_logging use dynFATESLandUseChangeMod, only : fates_harvest_clmlanduse use dynFATESLandUseChangeMod, only : fates_harvest_luh_area + use dynFATESLandUseChangeMod, only : fates_harvest_luh_mass use dynFATESLandUseChangeMod, only : landuse_harvest use dynFATESLandUseChangeMod, only : landuse_harvest_units use dynFATESLandUseChangeMod, only : landuse_harvest_varnames @@ -517,23 +518,28 @@ subroutine CLMFatesGlobals2() call set_fates_ctrlparms('use_cohort_age_tracking',ival=pass_cohort_age_tracking) ! FATES logging and harvest modes - if (fates_harvest_mode > fates_harvest_no_logging) then + 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 (fates_harvest_mode == fates_harvest_clmlanduse) then + if (trim(fates_harvest_mode) == fates_harvest_clmlanduse) then pass_num_lu_harvest_cats = num_harvest_inst pass_lu_harvest = 1 ! LUH2 landuse timeseries driven harvest rates - else if (fates_harvest_mode >= fates_harvest_luh_area) then + 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 - else - pass_lu_harvest = 0 - pass_num_lu_harvest_cats = 0 end if 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_cats) + call set_fates_ctrlparms('use_logging',ival=pass_logging) + ! FATES landuse modes if(use_fates_luh) then pass_use_luh = 1 @@ -556,11 +562,6 @@ subroutine CLMFatesGlobals2() end if call set_fates_ctrlparms('use_fates_potentialveg',ival=pass_use_potentialveg) - ! Wait to set the harvest and logging variables after checking fates_harvest_modes - call set_fates_ctrlparms('use_lu_harvest',ival=pass_lu_harvest) - 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_inventory_init) then pass_inventory_init = 1 else @@ -1069,7 +1070,7 @@ subroutine dynamics_driv(this, nc, bounds_clump, & call GetAndSetTime ! Get harvest rates for CLM landuse timeseries driven rates - if (fates_harvest_mode == fates_harvest_clmlanduse) then + if (trim(fates_harvest_mode) == fates_harvest_clmlanduse) then call dynHarvest_interp_resolve_harvesttypes(bounds_clump, & harvest_rates=harvest_rates(begg:endg,1:num_harvest_inst), & after_start_of_harvest_ts=after_start_of_harvest_ts) @@ -1195,7 +1196,7 @@ subroutine dynamics_driv(this, nc, bounds_clump, & ! for now there is one veg column per gridcell, so store all harvest data in each site ! this will eventually change ! today's hlm harvest flag needs to be set no matter what - if (fates_harvest_mode == fates_harvest_clmlanduse) then + if (trim(fates_harvest_mode) == fates_harvest_clmlanduse) then if (after_start_of_harvest_ts) then this%fates(nc)%bc_in(s)%hlm_harvest_rates(1:num_harvest_inst) = harvest_rates(g,1:num_harvest_inst) else @@ -1214,7 +1215,8 @@ subroutine dynamics_driv(this, nc, bounds_clump, & call endrun(msg=errMsg(sourcefile, __LINE__)) end if - else if (fates_harvest_mode >= fates_harvest_luh_area) then + 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 @@ -2181,7 +2183,8 @@ subroutine init_coldstart(this, waterstatebulk_inst, waterdiagnosticbulk_inst, & 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 (fates_harvest_mode >= fates_harvest_luh_area ) then + 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