From ee5ef88b1c5718ba40e1941991e4fd789d5c08eb Mon Sep 17 00:00:00 2001 From: Charlie Koven Date: Mon, 1 May 2023 21:08:22 -0700 Subject: [PATCH 01/10] adding land use parameters to file: grazing, PFT max canopy coverage --- parameter_files/fates_params_default.cdl | 26 ++++++++++++++++++++++++ tools/modify_fates_paramfile.py | 2 +- tools/ncvarsort.py | 7 +++++-- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 408ca1e9ab..70379cd60f 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -8,6 +8,7 @@ dimensions: fates_history_size_bins = 13 ; fates_hlm_pftno = 14 ; fates_hydr_organs = 4 ; + fates_landuseclass = 5 ; fates_leafage_class = 1 ; fates_litterclass = 6 ; fates_pft = 12 ; @@ -47,6 +48,9 @@ variables: char fates_litterclass_name(fates_litterclass, fates_string_length) ; fates_litterclass_name:units = "unitless - string" ; fates_litterclass_name:long_name = "Name of the litter classes, for variables associated with dimension fates_litterclass" ; + char fates_landuseclass_name(fates_landuseclass, fates_string_length) ; + fates_landuseclass_name:units = "unitless - string" ; + fates_landuseclass_name:long_name = "Name of the land use classes, for variables associated with dimension fates_landuseclass" ; double fates_alloc_organ_priority(fates_plant_organs, fates_pft) ; fates_alloc_organ_priority:units = "index" ; fates_alloc_organ_priority:long_name = "Priority level for allocation, 1: replaces turnover from storage, 2: same priority as storage use/replacement, 3: ascending in order of least importance" ; @@ -587,6 +591,12 @@ variables: double fates_frag_cwd_frac(fates_NCWD) ; fates_frag_cwd_frac:units = "fraction" ; fates_frag_cwd_frac:long_name = "fraction of woody (bdead+bsw) biomass destined for CWD pool" ; + double fates_landuse_grazing_rate(fates_landuseclass) ; + fates_landuse_grazing_rate:units = "1/day" ; + fates_landuse_grazing_rate:long_name = "fraction of leaf biomass consumed by grazers per day" ; + double fates_landuse_pft_maxcancov(fates_landuseclass, fates_pft) ; + fates_landuse_pft_maxcancov:units = "area fraction" ; + fates_landuse_pft_maxcancov:long_name = "Maximum canopy coverage of each PFT in each land use class" ; double fates_canopy_closure_thresh ; fates_canopy_closure_thresh:units = "unitless" ; fates_canopy_closure_thresh:long_name = "tree canopy coverage at which crown area allometry changes from savanna to forest value" ; @@ -860,6 +870,13 @@ data: "dead leaves ", "live grass " ; + fates_landuseclass_name = + "primaryland ", + "secondaryland ", + "rangeland ", + "pastureland ", + "cropland " ; + fates_alloc_organ_priority = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -1426,6 +1443,15 @@ data: fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; + fates_landuse_grazing_rate = 0.0, 0.0, 0.07, 0.07, 0.0 ; + + fates_landuse_pft_maxcancov = + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 1, 1, 1, + 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; + fates_canopy_closure_thresh = 0.8 ; fates_cnp_eca_plant_escalar = 1.25e-05 ; diff --git a/tools/modify_fates_paramfile.py b/tools/modify_fates_paramfile.py index adacb2457b..85f7c449ea 100755 --- a/tools/modify_fates_paramfile.py +++ b/tools/modify_fates_paramfile.py @@ -141,7 +141,7 @@ def main(): 'fates_history_damage_bins', 'fates_NCWD','fates_litterclass','fates_leafage_class', \ 'fates_plant_organs','fates_hydr_organs','fates_hlm_pftno', \ - 'fates_leafage_class']: + 'fates_leafage_class','fates_landuse_class']: otherdimpresent = True otherdimname = var.dimensions[i] otherdimlength = var.shape[i] diff --git a/tools/ncvarsort.py b/tools/ncvarsort.py index 327dd84a96..6583700ae3 100755 --- a/tools/ncvarsort.py +++ b/tools/ncvarsort.py @@ -30,7 +30,7 @@ def main(): # make empty lists to hold the variable names in. the first of these is a list of sub-lists, # one for each type of variable (based on dimensionality). # the second is the master list that will contain all variables. - varnames_list = [[],[],[],[],[],[],[],[],[],[],[],[],[]] + varnames_list = [[],[],[],[],[],[],[],[],[],[],[],[],[],[]] varnames_list_sorted = [] # # sort the variables by dimensionality, but mix the PFT x other dimension in with the regular PFT-indexed variables @@ -48,6 +48,7 @@ def main(): (u'fates_prt_organs', u'fates_string_length'):7, (u'fates_plant_organs', u'fates_string_length'):7, (u'fates_litterclass', u'fates_string_length'):7, + (u'fates_landuseclass', u'fates_string_length'):7, (u'fates_pft',):8, (u'fates_hydr_organs', u'fates_pft'):8, (u'fates_leafage_class', u'fates_pft'):8, @@ -56,7 +57,9 @@ def main(): (u'fates_hlm_pftno', u'fates_pft'):9, (u'fates_litterclass',):10, (u'fates_NCWD',):11, - ():12} + (u'fates_landuseclass',):12, + (u'fates_landuseclass', u'fates_pft'):12, + ():13} # # go through each of the variables and assign it to one of the sub-lists based on its dimensionality for v_name, varin in dsin.variables.items(): From dbd692d19866e71cf118518e10383e4b8dcc7aea Mon Sep 17 00:00:00 2001 From: Charlie Koven Date: Mon, 10 Jul 2023 16:23:56 -0700 Subject: [PATCH 02/10] starting to add grazing parameterization --- biogeochem/EDPhysiologyMod.F90 | 20 +++++++- main/EDMainMod.F90 | 7 ++- main/EDTypesMod.F90 | 3 ++ parameter_files/fates_params_default.cdl | 25 ++++++++++ parteh/PRTGenericMod.F90 | 48 ++++++++++++++++++-- parteh/PRTLossFluxesMod.F90 | 58 +++++++++++++++++++++++- 6 files changed, 155 insertions(+), 6 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 5c63524ef0..6d465dabd1 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2364,6 +2364,15 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) element_id = litt%element_id + select case(element): + case(carbon12_element): + herbivory_element_use_efficiency = fates_landuse_grazing_carbon_use_eff + case(nitrogen_element): + herbivory_element_use_efficiency = fates_landuse_grazing_nitrogen_use_eff + case (phosphorus_element): + herbivory_element_use_efficiency = fates_landuse_grazing_phosphorus_use_eff + end select + ! Object tracking flux diagnostics for each element flux_diags => currentSite%flux_diags(element_pos(element_id)) @@ -2384,6 +2393,8 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) fnrt_m = currentCohort%prt%GetState(fnrt_organ,element_id) repro_m = currentCohort%prt%GetState(repro_organ,element_id) + leaf_herbivory = currentCohort%prt%GetHerbivory(leaf_organ, element_id) + if (prt_params%woody(currentCohort%pft) == itrue) then ! Assumption: for woody plants fluxes from deadwood and sapwood go together in CWD pool leaf_m_turnover = currentCohort%prt%GetTurnover(leaf_organ,element_id) @@ -2428,7 +2439,9 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) do dcmpy=1,ndcmpy dcmpy_frac = GetDecompyFrac(pft,leaf_organ,dcmpy) litt%leaf_fines_in(dcmpy) = litt%leaf_fines_in(dcmpy) + & - (leaf_m_turnover+repro_m_turnover) * plant_dens * dcmpy_frac + (leaf_m_turnover+repro_m_turnover + & + leaf_herbivory * herbivory_element_use_efficiency) * & + plant_dens * dcmpy_frac dcmpy_frac = GetDecompyFrac(pft,fnrt_organ,dcmpy) do ilyr = 1, numlevsoil @@ -2441,6 +2454,11 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) flux_diags%root_litter_input(pft) + & (fnrt_m_turnover + store_m_turnover ) * currentCohort%n + ! send the part of the herbivory flux that doesn't go to litter to the atmosphere + + currentSite%mass_balance(element_id)%herbivory_flux_out = & + currentSite%mass_balance(element_id)%herbivory_flux_out + & + leaf_herbivory * (1._r8 - herbivory_element_use_efficiency) * currentCohort%n ! Assumption: turnover from deadwood and sapwood are lumped together in CWD pool diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 38a95f005a..5489842026 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -529,6 +529,9 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) bc_out%ar_site = bc_out%ar_site + currentCohort%resp_acc_hold * & AREA_INV * currentCohort%n / hlm_days_per_year / sec_per_day + ! allow herbivores to graze + call fates_grazing(currentCohort%prt, ft, currentPatch%land_use_label, currentCohort%hite) + ! Conduct Maintenance Turnover (parteh) if(debug) call currentCohort%prt%CheckMassConservation(ft,3) if(any(currentSite%dstatus == [phen_dstat_moiston,phen_dstat_timeon])) then @@ -920,7 +923,8 @@ subroutine TotalBalanceCheck (currentSite, call_index ) site_mass%seed_out + & site_mass%flux_generic_out + & site_mass%frag_out + & - site_mass%aresp_acc + site_mass%aresp_acc + & + site_mass%herbivory_flux_out net_flux = flux_in - flux_out error = abs(net_flux - change_in_stock) @@ -952,6 +956,7 @@ subroutine TotalBalanceCheck (currentSite, call_index ) write(fates_log(),*) 'flux_generic_out: ',site_mass%flux_generic_out write(fates_log(),*) 'frag_out: ',site_mass%frag_out write(fates_log(),*) 'aresp_acc: ',site_mass%aresp_acc + write(fates_log(),*) 'herbivory_flux: ',site_mass%herbivory_flux write(fates_log(),*) 'error=net_flux-dstock:', error write(fates_log(),*) 'biomass', biomass_stock write(fates_log(),*) 'litter',litter_stock diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 84c1fb7a4b..0eccb6c914 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -702,6 +702,8 @@ module EDTypesMod ! due to re-sizing patches when area math starts to lose ! precision + real(r8) :: herbivory_flux_out ! loss of element due to grazing (and/or browsing) by herbivores + contains procedure :: ZeroMassBalState @@ -978,6 +980,7 @@ subroutine ZeroMassBalFlux(this) this%flux_generic_in = 0._r8 this%flux_generic_out = 0._r8 this%patch_resize_err = 0._r8 + this%herbivory_flux_out= 0._r8 return end subroutine ZeroMassBalFlux diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 70379cd60f..9396db962e 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -342,6 +342,9 @@ variables: double fates_hydro_vg_n_node(fates_hydr_organs, fates_pft) ; fates_hydro_vg_n_node:units = "unitless" ; fates_hydro_vg_n_node:long_name = "(used if hydr_htftype_node = 2),n in van Genuchten 1980 model, pore size distribution parameter" ; + double fates_landuse_grazing_palatability(fates_pft) ; + fates_landuse_grazing_palatability:units = "unitless 0-1" ; + fates_landuse_grazing_palatability:long_name = "Relative intensity of leaf grazing/browsing per PFT" ; double fates_leaf_c3psn(fates_pft) ; fates_leaf_c3psn:units = "flag" ; fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; @@ -684,6 +687,18 @@ variables: double fates_hydro_solver ; fates_hydro_solver:units = "unitless" ; fates_hydro_solver:long_name = "switch designating which numerical solver for plant hydraulics, 1 = 1D taylor, 2 = 2D Picard, 3 = 2D Newton (deprecated)" ; + double fates_landuse_grazing_carbon_use_eff ; + fates_landuse_grazing_carbon_use_eff:units = "unitless" ; + fates_landuse_grazing_carbon_use_eff:long_name = "carbon use efficiency of material eaten by grazers/browsers (i.e. amount in manure / amount consumed)" ; + double fates_landuse_grazing_maxheight ; + fates_landuse_grazing_maxheight:units = "m" ; + fates_landuse_grazing_maxheight:long_name = "maximum height that grazers (browsers, actually) can reach" ; + double fates_landuse_grazing_nitrogen_use_eff ; + fates_landuse_grazing_nitrogen_use_eff:units = "unitless" ; + fates_landuse_grazing_nitrogen_use_eff:long_name = "nitrogen use efficiency of material eaten by grazers/browsers (i.e. amount in manure / amount consumed)" ; + double fates_landuse_grazing_phosphorus_use_eff ; + fates_landuse_grazing_phosphorus_use_eff:units = "unitless" ; + fates_landuse_grazing_phosphorus_use_eff:long_name = "phosphorus use efficiency of material eaten by grazers/browsers (i.e. amount in manure / amount consumed)" ; double fates_landuse_logging_coll_under_frac ; fates_landuse_logging_coll_under_frac:units = "fraction" ; fates_landuse_logging_coll_under_frac:long_name = "Fraction of stems killed in the understory when logging generates disturbance" ; @@ -1197,6 +1212,8 @@ data: 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; + fates_landuse_grazing_palatability = 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1 ; + fates_leaf_c3psn = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 ; fates_leaf_jmaxha = 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, @@ -1510,6 +1527,14 @@ data: fates_hydro_solver = 1 ; + fates_landuse_grazing_carbon_use_eff = 0. ; + + fates_landuse_grazing_maxheight = 1 ; + + fates_landuse_grazing_nitrogen_use_eff = 0.25 ; + + fates_landuse_grazing_phosphorus_use_eff = 0.5 ; + fates_landuse_logging_coll_under_frac = 0.55983 ; fates_landuse_logging_collateral_frac = 0.05 ; diff --git a/parteh/PRTGenericMod.F90 b/parteh/PRTGenericMod.F90 index 3f76517254..fec39013b6 100644 --- a/parteh/PRTGenericMod.F90 +++ b/parteh/PRTGenericMod.F90 @@ -189,8 +189,7 @@ module PRTGenericMod real(r8),allocatable :: burned(:) ! Losses due to burn [kg] real(r8),allocatable :: damaged(:) ! Losses due to damage [kg] - - ! real(r8),allocatable :: herbiv(:) ! Losses due to herbivory [kg] + real(r8),allocatable :: herbivory(:) ! Losses due to herbivory [kg] ! Placeholder ! To save on memory, keep this commented out, or simply @@ -261,6 +260,7 @@ module PRTGenericMod procedure, non_overridable :: GetState procedure, non_overridable :: GetTurnover procedure, non_overridable :: GetBurned + procedure, non_overridable :: GetHerbivory procedure, non_overridable :: GetNetAlloc procedure, non_overridable :: ZeroRates procedure, non_overridable :: CheckMassConservation @@ -549,6 +549,7 @@ subroutine InitAllocate(this) allocate(this%variables(i_var)%net_alloc(num_pos)) allocate(this%variables(i_var)%burned(num_pos)) allocate(this%variables(i_var)%damaged(num_pos)) + allocate(this%variables(i_var)%herbivory(num_pos)) end do @@ -576,6 +577,7 @@ subroutine InitializeInitialConditions(this) this%variables(i_var)%burned(:) = un_initialized this%variables(i_var)%damaged(:) = un_initialized this%variables(i_var)%net_alloc(:) = un_initialized + this%variables(i_var)%herbivory(:) = un_initialized end do ! Initialize the optimum step size as very large. @@ -796,6 +798,7 @@ subroutine CopyPRTVartypes(this, donor_prt_obj) this%variables(i_var)%turnover(:) = donor_prt_obj%variables(i_var)%turnover(:) this%variables(i_var)%burned(:) = donor_prt_obj%variables(i_var)%burned(:) this%variables(i_var)%damaged(:) = donor_prt_obj%variables(i_var)%damaged(:) + this%variables(i_var)%herbivory(:) = donor_prt_obj%variables(i_var)%herbivory(:) end do this%ode_opt_step = donor_prt_obj%ode_opt_step @@ -846,6 +849,8 @@ subroutine WeightedFusePRTVartypes(this,donor_prt_obj, recipient_fuse_weight) this%variables(i_var)%damaged(pos_id) = recipient_fuse_weight * this%variables(i_var)%damaged(pos_id) + & (1.0_r8-recipient_fuse_weight) * donor_prt_obj%variables(i_var)%damaged(pos_id) + this%variables(i_var)%herbivory(pos_id) = recipient_fuse_weight * this%variables(i_var)%herbivory(pos_id) + & + (1.0_r8-recipient_fuse_weight) * donor_prt_obj%variables(i_var)%herbivory(pos_id) end do end do @@ -887,6 +892,7 @@ subroutine DeallocatePRTVartypes(this) this%variables(i_var)%net_alloc, & this%variables(i_var)%turnover, & this%variables(i_var)%burned, & + this%variables(i_var)%herbivory, & stat=istat, errmsg=smsg ) if (istat/=0) call endrun(msg='DeallocatePRTVartypes 1 stat/=0:'//trim(smsg)//errMsg(sourcefile, __LINE__)) end do @@ -936,6 +942,7 @@ subroutine ZeroRates(this) this%variables(i_var)%net_alloc(:) = 0.0_r8 this%variables(i_var)%turnover(:) = 0.0_r8 this%variables(i_var)%burned(:) = 0.0_r8 + this%variables(i_var)%herbivory(:) = 0.0_r8 this%variables(i_var)%damaged(:) = 0.0_r8 end do @@ -973,6 +980,7 @@ subroutine CheckMassConservation(this,ipft,position_id) (this%variables(i_var)%net_alloc(i_pos) & -this%variables(i_var)%turnover(i_pos) & -this%variables(i_var)%burned(i_pos) & + -this%variables(i_var)%herbivory(i_pos) & -this%variables(i_var)%damaged(i_pos))) if(this%variables(i_var)%val(i_pos) > nearzero ) then @@ -998,7 +1006,8 @@ subroutine CheckMassConservation(this,ipft,position_id) this%variables(i_var)%val0(i_pos), & this%variables(i_var)%net_alloc(i_pos), & this%variables(i_var)%turnover(i_pos), & - this%variables(i_var)%burned(i_pos), & + this%variables(i_var)%burned(i_pos), & + this%variables(i_var)%herbivory(i_pos), & this%variables(i_var)%damaged(i_pos) write(fates_log(),*) ' Exiting.' call endrun(msg=errMsg(sourcefile, __LINE__)) @@ -1124,6 +1133,39 @@ function GetBurned(this, organ_id, element_id, position_id) result(burned_val) return end function GetBurned + ! ========================================================================= + + function GetHerbivory(this, organ_id, element_id, position_id) result(herbivory_val) + + ! This function is very very similar to GetBurned + + class(prt_vartypes) :: this + integer,intent(in) :: organ_id ! Organ type querried + integer,intent(in) :: element_id ! Element type querried + integer,intent(in),optional :: position_id ! Position querried + real(r8) :: herbivory_val ! Amount (value) of herbivory [kg] + integer :: i_pos ! position loop counter + integer :: i_var ! variable id + + if(present(position_id)) then + + i_pos = position_id + i_var = prt_global%sp_organ_map(organ_id,element_id) + herbivory_val = this%variables(i_var)%herbivory(i_pos) + + else + + herbivory_val = 0.0_r8 + i_var = prt_global%sp_organ_map(organ_id,element_id) + do i_pos = 1, prt_global%state_descriptor(i_var)%num_pos + herbivory_val = herbivory_val + this%variables(i_var)%herbivory(i_pos) + end do + + end if + + return + end function GetHerbivory + ! ==================================================================================== function GetNetAlloc(this, organ_id, element_id, position_id) result(val_netalloc) diff --git a/parteh/PRTLossFluxesMod.F90 b/parteh/PRTLossFluxesMod.F90 index f490b0749b..c040e88c2d 100644 --- a/parteh/PRTLossFluxesMod.F90 +++ b/parteh/PRTLossFluxesMod.F90 @@ -66,6 +66,7 @@ module PRTLossFluxesMod public :: PRTReproRelease public :: PRTDamageLosses public :: PRTDamageRecoveryFluxes + public :: PRTHerbivoryLosses contains @@ -863,7 +864,62 @@ subroutine PRTDamageRecoveryFluxes(prt, organ_id, mass_0, mass, cc_mass) + (mass - mass_0) end subroutine PRTDamageRecoveryFluxes - + + ! ===================================================================================== + + subroutine PRTHerbivoryLosses(prt, organ_id, mass_fraction) + + ! ---------------------------------------------------------------------------------- + ! This subroutine assumes that there is no re-translocation associated + ! with herbivory. There is only one destiny for eaten mass within + ! the organ, and that is outside the plant. + ! It is also assumed that non PARTEH parts of the code (ie the grazing-model) + ! will decide what to do with the consumed mass (i.e. sent it to the litter + ! pool or send to atmosphere) + ! ---------------------------------------------------------------------------------- + + class(prt_vartypes) :: prt + integer,intent(in) :: organ_id + real(r8),intent(in) :: mass_fraction + + integer :: i_pos ! position index + integer :: i_var ! index for the variable of interest + integer :: i_var_of_organ ! loop counter for all element in this organ + integer :: element_id ! Element id of the turnover pool + real(r8) :: herbivore_consumed_mass ! Consumed mass of each element, in each + ! position, in the organ of interest + + associate(organ_map => prt_global%organ_map) + + ! This is the total number of state variables associated + ! with this particular organ + + do i_var_of_organ = 1, organ_map(organ_id)%num_vars + + i_var = organ_map(organ_id)%var_id(i_var_of_organ) + + element_id = prt_global%state_descriptor(i_var)%element_id + + ! Loop over all of the coordinate ids + do i_pos = 1,prt_global%state_descriptor(i_var)%num_pos + + ! The mass that is leaving the plant + consumed_mass = mass_fraction * prt%variables(i_var)%val(i_pos) + + ! Track the amount of mass being eaten (+ is amount lost) + prt%variables(i_var)%herbivory(i_pos) = prt%variables(i_var)%herbivory(i_pos) & + + herbivore_consumed_mass + + ! Update the state of the pool to reflect the mass lost + prt%variables(i_var)%val(i_pos) = prt%variables(i_var)%val(i_pos) & + - herbivore_consumed_mass + + end do + + end do + + end associate + end subroutine PRTHerbivoryLosses ! ===================================================================================== From 580df9e05ac7346a827485c5a68bc0d35917b7df Mon Sep 17 00:00:00 2001 From: Charlie Koven Date: Tue, 11 Jul 2023 10:57:50 -0700 Subject: [PATCH 03/10] more grazing updates --- biogeochem/FatesLandUseChangeMod.F90 | 31 ++++++++++++++++++++++++ main/EDParamsMod.F90 | 9 +++++++ main/FatesParametersInterface.F90 | 1 + parameter_files/fates_params_default.cdl | 10 -------- 4 files changed, 41 insertions(+), 10 deletions(-) diff --git a/biogeochem/FatesLandUseChangeMod.F90 b/biogeochem/FatesLandUseChangeMod.F90 index 89b262ac12..1610048dd5 100644 --- a/biogeochem/FatesLandUseChangeMod.F90 +++ b/biogeochem/FatesLandUseChangeMod.F90 @@ -29,6 +29,7 @@ module FatesLandUseChangeMod public :: get_landuse_transition_rates public :: get_landusechange_rules public :: get_luh_statedata + public :: fates_grazing ! module data @@ -298,4 +299,34 @@ subroutine CheckLUHData(luh_vector,modified_flag) end subroutine CheckLUHData + !---------------------------------------------------------------------------------------------------- + + subroutine fates_grazing(prt, ft, land_use_label, hite) + + use PRTGenericMod, only : leaf_organ + use PRTGenericMod, only : prt_vartypes + use PRTLossFluxesMod, only : PRTHerbivoryLosses + + ! apply grazing and browsing to plants as a function of PFT, height (for woody plants), and land use label. + + class(prt_vartypes), intent(inout), pointer :: prt + integer, intent(in) :: ft + integer, intent(in) :: land_use-label + real(r8), intent(in) :: hite + + real(r8) :: grazing_rate ! rate of grazing (or browsing) of leaf tissue [day -1] + + grazing_rate = fates_landuse_grazing_rate(land_use_label) * fates_landuse_grazing_palatability(ft) + + if ( grazing_rate .gt. 0._r8) then + if (woody(ft)) then + grazing_rate = grazing_rate * & + max(0._r8, min(1._r8, (fates_landuse_grazing_maxheight - hite*fates_allom_crown_depth_frac(ft)/(hite - hite*fates_allom_crown_depth_frac(ft))))) + endif + + call PRTHerbivoryLosses(prt, leaf_organ, grazing_rate) + end if + + end subroutine fates_grazing + end module FatesLandUseChangeMod diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 9a54a45db5..cd1dff8bc1 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -134,6 +134,7 @@ module EDParamsMod character(len=param_string_length),parameter,public :: ED_name_history_coageclass_bin_edges = "fates_history_coageclass_bin_edges" character(len=param_string_length),parameter,public :: ED_name_history_damage_bin_edges = "fates_history_damage_bin_edges" + ! Hydraulics Control Parameters (ONLY RELEVANT WHEN USE_FATES_HYDR = TRUE) ! ---------------------------------------------------------------------------------------------- real(r8),protected,public :: hydr_kmax_rsurf1 ! maximum conducitivity for unit root surface @@ -246,6 +247,14 @@ module EDParamsMod ! product pool (pprodharv10) of all woody PFT types character(len=param_string_length),parameter,public :: logging_name_pprodharv10="fates_landuse_pprodharv10_forest_mean" + ! grazing-related parameters + character(len=param_string_length),parameter,public :: ED_name_landuse_grazing_palatability = "fates_landuse_grazing_palatability" + character(len=param_string_length),parameter,public :: ED_name_landuse_grazing_rate = "fates_landuse_grazing_rate" + character(len=param_string_length),parameter,public :: ED_name_landuse_grazing_carbon_use_eff = "fates_landuse_grazing_carbon_use_eff" + character(len=param_string_length),parameter,public :: ED_name_landuse_grazing_maxheight = "fates_landuse_grazing_maxheight" + character(len=param_string_length),parameter,public :: ED_name_landuse_grazing_nitrogen_use_eff = "fates_landuse_grazing_nitrogen_use_eff" + character(len=param_string_length),parameter,public :: ED_name_landuse_grazing_phosphorus_use_eff = "fates_landuse_grazing_phosphorus_use_eff" + real(r8),protected,public :: eca_plant_escalar ! scaling factor for plant fine root biomass to ! calculate nutrient carrier enzyme abundance (ECA) diff --git a/main/FatesParametersInterface.F90 b/main/FatesParametersInterface.F90 index aa13150c4a..3bb0f9a30b 100644 --- a/main/FatesParametersInterface.F90 +++ b/main/FatesParametersInterface.F90 @@ -38,6 +38,7 @@ module FatesParametersInterface character(len=*), parameter, public :: dimension_name_hlm_pftno = 'fates_hlm_pftno' character(len=*), parameter, public :: dimension_name_history_damage_bins = 'fates_history_damage_bins' character(len=*), parameter, public :: dimension_name_damage = 'fates_damage_class' + character(len=*), parameter, public :: dimension_name_landuse = 'fates_landuseclass' ! Dimensions in the host namespace: character(len=*), parameter, public :: dimension_name_host_allpfts = 'allpfts' diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 9396db962e..a84c30f541 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -597,9 +597,6 @@ variables: double fates_landuse_grazing_rate(fates_landuseclass) ; fates_landuse_grazing_rate:units = "1/day" ; fates_landuse_grazing_rate:long_name = "fraction of leaf biomass consumed by grazers per day" ; - double fates_landuse_pft_maxcancov(fates_landuseclass, fates_pft) ; - fates_landuse_pft_maxcancov:units = "area fraction" ; - fates_landuse_pft_maxcancov:long_name = "Maximum canopy coverage of each PFT in each land use class" ; double fates_canopy_closure_thresh ; fates_canopy_closure_thresh:units = "unitless" ; fates_canopy_closure_thresh:long_name = "tree canopy coverage at which crown area allometry changes from savanna to forest value" ; @@ -1462,13 +1459,6 @@ data: fates_landuse_grazing_rate = 0.0, 0.0, 0.07, 0.07, 0.0 ; - fates_landuse_pft_maxcancov = - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 1, 1, 1, - 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; - fates_canopy_closure_thresh = 0.8 ; fates_cnp_eca_plant_escalar = 1.25e-05 ; From cb5ea6d3691f079c1029c9fff9cb392b2836cf9b Mon Sep 17 00:00:00 2001 From: Charlie Koven Date: Mon, 18 Sep 2023 16:57:15 -0700 Subject: [PATCH 04/10] fixed merged conflict --- parameter_files/fates_params_default.cdl | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 5e31abf1d3..4c18174c6f 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -52,9 +52,6 @@ variables: char fates_litterclass_name(fates_litterclass, fates_string_length) ; fates_litterclass_name:units = "unitless - string" ; fates_litterclass_name:long_name = "Name of the litter classes, for variables associated with dimension fates_litterclass" ; - char fates_landuseclass_name(fates_landuseclass, fates_string_length) ; - fates_landuseclass_name:units = "unitless - string" ; - fates_landuseclass_name:long_name = "Name of the land use classes, for variables associated with dimension fates_landuseclass" ; double fates_alloc_organ_priority(fates_plant_organs, fates_pft) ; fates_alloc_organ_priority:units = "index" ; fates_alloc_organ_priority:long_name = "Priority level for allocation, 1: replaces turnover from storage, 2: same priority as storage use/replacement, 3: ascending in order of least importance" ; @@ -968,13 +965,6 @@ data: "dead leaves ", "live grass " ; - fates_landuseclass_name = - "primaryland ", - "secondaryland ", - "rangeland ", - "pastureland ", - "cropland " ; - fates_alloc_organ_priority = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, From 4e818e820539a14d5e2ae7a19c3c673c4bfcef72 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Mon, 18 Dec 2023 21:46:24 -0800 Subject: [PATCH 05/10] changed hite to height --- biogeochem/FatesLandUseChangeMod.F90 | 6 +++--- main/EDMainMod.F90 | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/biogeochem/FatesLandUseChangeMod.F90 b/biogeochem/FatesLandUseChangeMod.F90 index 2e53a2e0e3..33f5fb66d1 100644 --- a/biogeochem/FatesLandUseChangeMod.F90 +++ b/biogeochem/FatesLandUseChangeMod.F90 @@ -318,7 +318,7 @@ end subroutine CheckLUHData !---------------------------------------------------------------------------------------------------- - subroutine fates_grazing(prt, ft, land_use_label, hite) + subroutine fates_grazing(prt, ft, land_use_label, height) use PRTGenericMod, only : leaf_organ use PRTGenericMod, only : prt_vartypes @@ -329,7 +329,7 @@ subroutine fates_grazing(prt, ft, land_use_label, hite) class(prt_vartypes), intent(inout), pointer :: prt integer, intent(in) :: ft integer, intent(in) :: land_use-label - real(r8), intent(in) :: hite + real(r8), intent(in) :: height real(r8) :: grazing_rate ! rate of grazing (or browsing) of leaf tissue [day -1] @@ -338,7 +338,7 @@ subroutine fates_grazing(prt, ft, land_use_label, hite) if ( grazing_rate .gt. 0._r8) then if (woody(ft)) then grazing_rate = grazing_rate * & - max(0._r8, min(1._r8, (fates_landuse_grazing_maxheight - hite*fates_allom_crown_depth_frac(ft)/(hite - hite*fates_allom_crown_depth_frac(ft))))) + max(0._r8, min(1._r8, (fates_landuse_grazing_maxheight - height*fates_allom_crown_depth_frac(ft)/(height - height*fates_allom_crown_depth_frac(ft))))) endif call PRTHerbivoryLosses(prt, leaf_organ, grazing_rate) diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 880a0f56a1..f05b57d7c2 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -525,7 +525,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) AREA_INV * currentCohort%n / hlm_days_per_year / sec_per_day ! allow herbivores to graze - call fates_grazing(currentCohort%prt, ft, currentPatch%land_use_label, currentCohort%hite) + call fates_grazing(currentCohort%prt, ft, currentPatch%land_use_label, currentCohort%height) ! Conduct Maintenance Turnover (parteh) if(debug) call currentCohort%prt%CheckMassConservation(ft,3) From b67019d45a031db984910d038c97ff667f118b58 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Tue, 19 Dec 2023 08:22:38 -0800 Subject: [PATCH 06/10] changed grazing rate to 4%/day --- parameter_files/fates_params_default.cdl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 459cdefa7c..0f4e16ef0b 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1617,7 +1617,7 @@ data: fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; - fates_landuse_grazing_rate = 0.0, 0.0, 0.07, 0.07, 0.0 ; + fates_landuse_grazing_rate = 0.0, 0.0, 0.04, 0.04, 0.0 ; fates_maxpatches_by_landuse = 9, 4, 1, 1, 1 ; From 636e003a602c01d63e98d1c37cb57dfcb2f4af73 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Fri, 19 Jul 2024 14:32:09 -0700 Subject: [PATCH 07/10] read the grazing parameters --- main/EDParamsMod.F90 | 65 +++++++++++++++++++++++++++++++++++++++----- main/EDPftvarcon.F90 | 13 ++++++++- 2 files changed, 70 insertions(+), 8 deletions(-) diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index b0763bbbde..d9d118183a 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -117,6 +117,13 @@ module EDParamsMod real(r8),protected,public :: q10_mr ! Q10 for respiration rate (for soil fragmenation and plant respiration) (unitless) real(r8),protected,public :: q10_froz ! Q10 for frozen-soil respiration rates (for soil fragmentation) (unitless) + ! grazing parameters + real(r8),protected,public :: landuse_grazing_carbon_use_eff + real(r8),protected,public :: landuse_grazing_maxheight + real(r8),protected,public :: landuse_grazing_nitrogen_use_eff + real(r8),protected,public :: landuse_grazing_phosphorus_use_eff + real(r8),protected,public :: landuse_grazing_rate(n_landuse_cats) + ! Unassociated pft dimensioned free parameter that developers can use for testing arbitrary new hypotheses ! (THIS PARAMETER IS UNUSED, FEEL FREE TO USE IT FOR WHATEVER PURPOSE YOU LIKE. WE CAN ! HELP MIGRATE YOUR USAGE OF THE PARMETER TO A PERMANENT HOME LATER) @@ -287,12 +294,11 @@ module EDParamsMod character(len=param_string_length),parameter,public :: logging_name_export_frac ="fates_landuse_logging_export_frac" ! grazing-related parameters - character(len=param_string_length),parameter,public :: ED_name_landuse_grazing_palatability = "fates_landuse_grazing_palatability" - character(len=param_string_length),parameter,public :: ED_name_landuse_grazing_rate = "fates_landuse_grazing_rate" - character(len=param_string_length),parameter,public :: ED_name_landuse_grazing_carbon_use_eff = "fates_landuse_grazing_carbon_use_eff" - character(len=param_string_length),parameter,public :: ED_name_landuse_grazing_maxheight = "fates_landuse_grazing_maxheight" - character(len=param_string_length),parameter,public :: ED_name_landuse_grazing_nitrogen_use_eff = "fates_landuse_grazing_nitrogen_use_eff" - character(len=param_string_length),parameter,public :: ED_name_landuse_grazing_phosphorus_use_eff = "fates_landuse_grazing_phosphorus_use_eff" + character(len=param_string_length),parameter,public :: name_landuse_grazing_rate = "fates_landuse_grazing_rate" + character(len=param_string_length),parameter,public :: name_landuse_grazing_carbon_use_eff = "fates_landuse_grazing_carbon_use_eff" + character(len=param_string_length),parameter,public :: name_landuse_grazing_maxheight = "fates_landuse_grazing_maxheight" + character(len=param_string_length),parameter,public :: name_landuse_grazing_nitrogen_use_eff = "fates_landuse_grazing_nitrogen_use_eff" + character(len=param_string_length),parameter,public :: name_landuse_grazing_phosphorus_use_eff = "fates_landuse_grazing_phosphorus_use_eff" real(r8),protected,public :: eca_plant_escalar ! scaling factor for plant fine root biomass to ! calculate nutrient carrier enzyme abundance (ECA) @@ -377,6 +383,12 @@ subroutine FatesParamsInit() dev_arbitrary = nan damage_event_code = -9 damage_canopy_layer_code = -9 + landuse_grazing_carbon_use_eff = nan + landuse_grazing_nitrogen_use_eff = nan + landuse_grazing_phosphorus_use_eff = nan + landuse_grazing_maxheight = nan + landuse_grazing_rate(:) = nan + end subroutine FatesParamsInit !----------------------------------------------------------------------- @@ -580,7 +592,19 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=damage_name_canopy_layer_code, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) - + + call fates_params%RegisterParameter(name=name_landuse_grazing_carbon_use_eff, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + + call fates_params%RegisterParameter(name=name_landuse_grazing_maxheight, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + + call fates_params%RegisterParameter(name=name_landuse_grazing_nitrogen_use_eff, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + + call fates_params%RegisterParameter(name=name_landuse_grazing_phosporus_use_eff, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + ! non-scalar parameters call fates_params%RegisterParameter(name=ED_name_hydr_htftype_node, dimension_shape=dimension_shape_1d, & @@ -616,6 +640,8 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=ED_name_max_nocomp_pfts_by_landuse, dimension_shape=dimension_shape_1d, & dimension_names=dim_names_landuse) + call fates_params%RegisterParameter(name=name_landuse_grazing_rate, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names_landuse) end subroutine FatesRegisterParams @@ -634,6 +660,7 @@ subroutine FatesReceiveParams(fates_params) real(r8), allocatable :: tmp_vector_by_landuse1(:) ! local real vector for changing type on read real(r8), allocatable :: tmp_vector_by_landuse2(:) ! local real vector for changing type on read real(r8), allocatable :: tmp_vector_by_landuse3(:) ! local real vector for changing type on read + real(r8), allocatable :: tmp_vector_by_landuse4(:) ! local real vector for changing type on read call fates_params%RetrieveParameter(name=ED_name_photo_temp_acclim_timescale, & data=photo_temp_acclim_timescale) @@ -869,6 +896,25 @@ subroutine FatesReceiveParams(fates_params) hydr_htftype_node(:) = nint(hydr_htftype_real(:)) deallocate(hydr_htftype_real) + call fates_params%RetrieveParameter(name=name_landuse_grazing_carbon_use_eff, & + data=landuse_grazing_carbon_use_eff) + + call fates_params%RetrieveParameter(name=name_landuse_grazing_nitrogen_use_eff, & + data=landuse_grazing_nitrogen_use_eff) + + call fates_params%RetrieveParameter(name=name_landuse_grazing_phosphorus_use_eff, & + data=landuse_grazing_phosphorus_use_eff) + + call fates_params%RetrieveParameter(name=name_landuse_grazing_maxheight, & + data=landuse_grazing_maxheight) + + call fates_params%RetrieveParameterAllocate(name=name_landuse_grazing_rate, & + data=tmp_vector_by_landuse4) + + landuse_grazing_rate(:) = tmp_vector_by_landuse4(:) + + deallocate(tmp_vector_by_landuse4) + end subroutine FatesReceiveParams ! ===================================================================================== @@ -939,6 +985,11 @@ subroutine FatesReportParams(is_master) write(fates_log(),'(a,L2)') 'active_crown_fire = ',active_crown_fire write(fates_log(),fmt0) 'damage_event_code = ',damage_event_code write(fates_log(),fmt0) 'damage_canopy_layer_code = ', damage_canopy_layer_code + write(fates_log(),fmt0) 'landuse_grazing_carbon_use_eff = ', landuse_grazing_carbon_use_eff + write(fates_log(),fmt0) 'name_landuse_grazing_nitrogen_use_eff = ', name_landuse_grazing_nitrogen_use_eff + write(fates_log(),fmt0) 'name_landuse_grazing_phosphorus_use_eff = ', name_landuse_grazing_phosphorus_use_eff + write(fates_log(),fmt0) 'name_landuse_grazing_maxheight = ', name_landuse_grazing_maxheight + write(fates_log(),fmt0) 'name_landuse_grazing_rate(:) = ', name_landuse_grazing_rate(:) write(fates_log(),*) '------------------------------------------------------' end if diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 8e10ebdcf7..4e7d267c95 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -286,6 +286,9 @@ module EDPftvarcon real(r8), allocatable :: landusechange_frac_exported(:) ! fraction of land use change-generated wood material that is exported to wood product (the remainder is either burned or goes to litter) real(r8), allocatable :: landusechange_pprod10(:) ! fraction of land use change wood product that goes to 10-year product pool (remainder goes to 100-year pool) + ! Grazing + real(r8), allocatable :: landuse_grazing_palatability(:) ! Relative intensity of leaf grazing/browsing per PFT (unitless 0-1) + contains procedure, public :: Init => EDpftconInit procedure, public :: Register @@ -818,7 +821,11 @@ subroutine Register_PFT(this, fates_params) name = 'fates_landuse_luc_pprod10' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - + + name = 'fates_landuse_grazing_palatability' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_dev_arbitrary_pft' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -1303,6 +1310,10 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetrieveParameterAllocate(name=name, & data=this%landusechange_pprod10) + name = 'fates_landuse_grazing_palatability' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%landuse_grazing_palatability) + end subroutine Receive_PFT !----------------------------------------------------------------------- From 2b87e44841d3f332aa01b974b31afd634fba714d Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Wed, 24 Jul 2024 09:37:12 -0700 Subject: [PATCH 08/10] set all grazing_rate parameters to zero --- parameter_files/fates_params_default.cdl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 527fc520df..adbb840160 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1679,7 +1679,7 @@ data: fates_landuse_crop_lu_pft_vector = -999, -999, -999, -999, 11 ; - fates_landuse_grazing_rate = 0.0, 0.0, 0.04, 0.04, 0.0 ; + fates_landuse_grazing_rate = 0.0, 0.0, 0.0, 0.0, 0.0 ; fates_max_nocomp_pfts_by_landuse = 4, 4, 1, 1, 1 ; From c039964e01e75e1bbab9b5c471693262f2556638 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Wed, 24 Jul 2024 17:24:05 -0700 Subject: [PATCH 09/10] compile-time bugfixes --- biogeochem/EDPhysiologyMod.F90 | 20 ++++++++++++-------- biogeochem/FatesLandUseChangeMod.F90 | 22 ++++++++++++++++------ main/EDMainMod.F90 | 3 ++- main/EDParamsMod.F90 | 2 +- parteh/PRTLossFluxesMod.F90 | 2 +- 5 files changed, 32 insertions(+), 17 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 98d0d4b571..591f0e1650 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2785,7 +2785,9 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) ! and turnover in dying trees. ! ! !USES: - + use EDParamsMod , only : landuse_grazing_carbon_use_eff + use EDParamsMod , only : landuse_grazing_nitrogen_use_eff + use EDParamsMod , only : landuse_grazing_phosphorus_use_eff ! ! !ARGUMENTS type(ed_site_type), intent(inout), target :: currentSite @@ -2832,6 +2834,8 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) integer :: numlevsoil ! Actual number of soil layers real(r8) :: SF_val_CWD_frac_adj(4) !SF_val_CWD_frac adjusted based on cohort dbh + real(r8) :: leaf_herbivory + real(r8) :: herbivory_element_use_efficiency !---------------------------------------------------------------------- ! ----------------------------------------------------------------------------------- @@ -2842,13 +2846,13 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) element_id = litt%element_id - select case(element): - case(carbon12_element): - herbivory_element_use_efficiency = fates_landuse_grazing_carbon_use_eff - case(nitrogen_element): - herbivory_element_use_efficiency = fates_landuse_grazing_nitrogen_use_eff - case (phosphorus_element): - herbivory_element_use_efficiency = fates_landuse_grazing_phosphorus_use_eff + select case(element_id) + case (carbon12_element) + herbivory_element_use_efficiency = landuse_grazing_carbon_use_eff + case (nitrogen_element) + herbivory_element_use_efficiency = landuse_grazing_nitrogen_use_eff + case (phosphorus_element) + herbivory_element_use_efficiency = landuse_grazing_phosphorus_use_eff end select ! Object tracking flux diagnostics for each element diff --git a/biogeochem/FatesLandUseChangeMod.F90 b/biogeochem/FatesLandUseChangeMod.F90 index 6e825a9b4d..0a51d8a02a 100644 --- a/biogeochem/FatesLandUseChangeMod.F90 +++ b/biogeochem/FatesLandUseChangeMod.F90 @@ -432,22 +432,32 @@ subroutine fates_grazing(prt, ft, land_use_label, height) use PRTGenericMod, only : leaf_organ use PRTGenericMod, only : prt_vartypes use PRTLossFluxesMod, only : PRTHerbivoryLosses + use EDParamsMod , only : landuse_grazing_rate + use EDParamsMod , only : landuse_grazing_maxheight + use EDPftvarcon , only : EDPftvarcon_inst + use PRTParametersMod, only : prt_params + use FatesAllometryMod,only : CrownDepth ! apply grazing and browsing to plants as a function of PFT, height (for woody plants), and land use label. class(prt_vartypes), intent(inout), pointer :: prt integer, intent(in) :: ft - integer, intent(in) :: land_use-label + integer, intent(in) :: land_use_label real(r8), intent(in) :: height real(r8) :: grazing_rate ! rate of grazing (or browsing) of leaf tissue [day -1] - - grazing_rate = fates_landuse_grazing_rate(land_use_label) * fates_landuse_grazing_palatability(ft) - + real(r8) :: crown_depth + + grazing_rate = landuse_grazing_rate(land_use_label) * EDPftvarcon_inst%landuse_grazing_palatability(ft) + if ( grazing_rate .gt. 0._r8) then - if (woody(ft)) then + if (prt_params%woody(ft)) then + + call CrownDepth(height,ft,crown_depth) + grazing_rate = grazing_rate * & - max(0._r8, min(1._r8, (fates_landuse_grazing_maxheight - height*fates_allom_crown_depth_frac(ft)/(height - height*fates_allom_crown_depth_frac(ft))))) + max(0._r8, min(1._r8, & + (landuse_grazing_maxheight - (height - crown_depth )) / crown_depth)) endif call PRTHerbivoryLosses(prt, leaf_organ, grazing_rate) diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 1b24a940db..0ecdcd786b 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -104,6 +104,7 @@ module EDMainMod use PRTLossFluxesMod, only : PRTReproRelease use EDPftvarcon, only : EDPftvarcon_inst use FatesHistoryInterfaceMod, only : fates_hist + use FatesLandUseChangeMod, only: fates_grazing ! CIME Globals use shr_log_mod , only : errMsg => shr_log_errMsg @@ -955,7 +956,7 @@ subroutine TotalBalanceCheck (currentSite, call_index ) write(fates_log(),*) 'flux_generic_out: ',site_mass%flux_generic_out write(fates_log(),*) 'frag_out: ',site_mass%frag_out write(fates_log(),*) 'aresp_acc: ',site_mass%aresp_acc - write(fates_log(),*) 'herbivory_flux: ',site_mass%herbivory_flux + write(fates_log(),*) 'herbivory_flux_out: ',site_mass%herbivory_flux_out write(fates_log(),*) 'error=net_flux-dstock:', error write(fates_log(),*) 'biomass', biomass_stock write(fates_log(),*) 'litter',litter_stock diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index d9d118183a..ee1523454c 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -602,7 +602,7 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=name_landuse_grazing_nitrogen_use_eff, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) - call fates_params%RegisterParameter(name=name_landuse_grazing_phosporus_use_eff, dimension_shape=dimension_shape_scalar, & + call fates_params%RegisterParameter(name=name_landuse_grazing_phosphorus_use_eff, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) ! non-scalar parameters diff --git a/parteh/PRTLossFluxesMod.F90 b/parteh/PRTLossFluxesMod.F90 index a43e7b4612..d0dcf0ca42 100644 --- a/parteh/PRTLossFluxesMod.F90 +++ b/parteh/PRTLossFluxesMod.F90 @@ -918,7 +918,7 @@ subroutine PRTHerbivoryLosses(prt, organ_id, mass_fraction) do i_pos = 1,prt_global%state_descriptor(i_var)%num_pos ! The mass that is leaving the plant - consumed_mass = mass_fraction * prt%variables(i_var)%val(i_pos) + herbivore_consumed_mass = mass_fraction * prt%variables(i_var)%val(i_pos) ! Track the amount of mass being eaten (+ is amount lost) prt%variables(i_var)%herbivory(i_pos) = prt%variables(i_var)%herbivory(i_pos) & From e7b236b8412f46332fb76ebf1d63551ad887b9a2 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Wed, 30 Oct 2024 19:39:29 -0700 Subject: [PATCH 10/10] added grazing carbon flux history variable --- main/FatesHistoryInterfaceMod.F90 | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index c5b48735f6..dcf26d9384 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -470,6 +470,7 @@ module FatesHistoryInterfaceMod integer :: ih_npp_agsw_si_scpf integer :: ih_npp_agdw_si_scpf integer :: ih_npp_stor_si_scpf + integer :: ih_grazing_si integer :: ih_mortality_canopy_si_scpf integer :: ih_mortality_understory_si_scpf @@ -2388,6 +2389,7 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) real(r8) :: fnrt_m_net_alloc ! mass allocated to fine-root [kg/yr] real(r8) :: struct_m_net_alloc ! mass allocated to structure [kg/yr] real(r8) :: repro_m_net_alloc ! mass allocated to reproduction [kg/yr] + real(r8) :: leaf_herbivory ! mass of leaves eaten by herbivores [kg/yr] real(r8) :: n_perm2 ! abundance per m2 real(r8) :: area_frac ! Fraction of area for this patch @@ -2440,6 +2442,7 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) hio_npp_froot_si => this%hvars(ih_npp_froot_si)%r81d, & hio_npp_croot_si => this%hvars(ih_npp_croot_si)%r81d, & hio_npp_stor_si => this%hvars(ih_npp_stor_si)%r81d, & + hio_grazing_si => this%hvars(ih_grazing_si)%r81d, & hio_canopy_mortality_crownarea_si => this%hvars(ih_canopy_mortality_crownarea_si)%r81d, & hio_ustory_mortality_crownarea_si => this%hvars(ih_understory_mortality_crownarea_si)%r81d, & hio_fire_c_to_atm_si => this%hvars(ih_fire_c_to_atm_si)%r81d, & @@ -2891,6 +2894,9 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) hio_npp_stor_si(io_si) = hio_npp_stor_si(io_si) + & store_m_net_alloc * n_perm2 / days_per_year / sec_per_day + leaf_herbivory = ccohort%prt%GetHerbivory(leaf_organ, carbon12_element) * days_per_year !cdkcdk + hio_grazing_si(io_si) = hio_grazing_si(io_si) + leaf_herbivory * n_perm2 / days_per_year / sec_per_day + ! Woody State Variables (basal area growth increment) if ( prt_params%woody(ft) == itrue) then @@ -6753,6 +6759,12 @@ subroutine define_history_vars(this, initialize_variables) upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_npp_stor_si) + call this%set_history_var(vname='FATES_GRAZING', units='kg m-2 s-1', & + long='grazing by herbivores of leaves in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_grazing_si) + hydro_active_if: if(hlm_use_planthydro.eq.itrue) then call this%set_history_var(vname='FATES_VEGH2O_DEAD', units = 'kg m-2', & long='cumulative water stored in dead biomass due to mortality', &