From 2fa63533c961449ecbbbd3209adb4229cde35ce7 Mon Sep 17 00:00:00 2001 From: jenniferholm Date: Tue, 13 Feb 2024 21:19:56 -0800 Subject: [PATCH 1/6] adding user switch for turning on and off daylength factor scalingfor photosynthesis parameters --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 31 ++++++++++++++++++++-- main/EDParamsMod.F90 | 13 ++++++++- parameter_files/fates_params_default.cdl | 5 ++++ 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 744e43ec16..1d947d74bb 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -62,6 +62,7 @@ module FATESPlantRespPhotosynthMod use EDParamsMod, only : maintresp_nonleaf_baserate use EDParamsMod, only : stomatal_model use EDParamsMod, only : stomatal_assim_model + use EDParamsMod, only : dayl_switch use EDParamsMod, only : photo_tempsens_model use PRTParametersMod, only : prt_params use EDPftvarcon , only : EDPftvarcon_inst @@ -109,6 +110,10 @@ module FATESPlantRespPhotosynthMod integer, parameter :: medlyn_model = 2 integer, parameter :: ballberry_model = 1 + ! Constants used to define day_length switch for scaling photosynthetic parameters + integer, parameter :: dayl_on = 1 + integer, parameter :: dayl_off = 2 + ! Alternatively, Gross Assimilation can be used to estimate ! leaf co2 partial pressure and therefore conductance. The default ! is to use anet @@ -595,6 +600,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) nscaler, & ! in ft, & ! in bc_in(s)%t_veg_pa(ifp), & ! in + bc_in(s)%dayl_factor_pa(ifp), & ! in currentPatch%tveg_lpa%GetMean(), & ! in lmr_z(iv,ft,cl)) ! out @@ -680,6 +686,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) currentCohort%kp25top, & ! in nscaler, & ! in bc_in(s)%t_veg_pa(ifp), & ! in + bc_in(s)%dayl_factor_pa(ifp), & ! in currentPatch%tveg_lpa%GetMean(), & ! in currentPatch%tveg_longterm%GetMean(),& ! in btran_eff, & ! in @@ -2325,6 +2332,7 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & nscaler, & ft, & veg_tempk, & + dayl_factor, & tgrowth, & lmr) @@ -2343,6 +2351,7 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & integer, intent(in) :: ft ! (plant) Functional Type Index real(r8), intent(in) :: nscaler ! Scale for leaf nitrogen profile real(r8), intent(in) :: veg_tempk ! vegetation temperature (degrees K) + real(r8), intent(in) :: dayl_factor ! daylength scaling factor (0-1) real(r8), intent(in) :: tgrowth ! lagged vegetation temperature averaged over acclimation timescale (degrees K) real(r8), intent(out) :: lmr ! Leaf Maintenance Respiration (umol CO2/m**2/s) @@ -2386,6 +2395,7 @@ subroutine LeafLayerBiophysicalRates( parsun_per_la, & co2_rcurve_islope25top_ft, & nscaler, & veg_tempk, & + dayl_factor, & t_growth, & t_home, & btran, & @@ -2421,6 +2431,7 @@ subroutine LeafLayerBiophysicalRates( parsun_per_la, & real(r8), intent(in) :: co2_rcurve_islope25top_ft ! initial slope of CO2 response curve ! (C4 plants) at 25C, canopy top, this pft real(r8), intent(in) :: veg_tempk ! vegetation temperature + real(r8), intent(in) :: dayl_factor ! daylength scaling factor (0-1) real(r8), intent(in) :: t_growth ! T_growth (short-term running mean temperature) (K) real(r8), intent(in) :: t_home ! T_home (long-term running mean temperature) (K) real(r8), intent(in) :: btran ! transpiration wetness factor (0 to 1) @@ -2486,11 +2497,12 @@ subroutine LeafLayerBiophysicalRates( parsun_per_la, & co2_rcurve_islope = 0._r8 else ! day time + if ( dayl_switch == dayl_on ) then ! Vcmax25top was already calculated to derive the nscaler function - vcmax25 = vcmax25top_ft * nscaler + vcmax25 = vcmax25top_ft * nscaler * dayl_factor select case(photo_tempsens_model) case (photosynth_acclim_model_none) - jmax25 = jmax25top_ft * nscaler + jmax25 = jmax25top_ft * nscaler * dayl_factor case (photosynth_acclim_model_kumarathunge_etal_2019) jmax25 = vcmax25*jvr case default @@ -2498,6 +2510,21 @@ subroutine LeafLayerBiophysicalRates( parsun_per_la, & call endrun(msg=errMsg(sourcefile, __LINE__)) end select + else if ( dayl_switch == dayl_off ) then + ! Vcmax25top was already calculated to derive the nscaler function + vcmax25 = vcmax25top_ft * nscaler + select case(photo_tempsens_model) + case (photosynth_acclim_model_none) + jmax25 = jmax25top_ft * nscaler + case (photosynth_acclim_model_kumarathunge_etal_2019) + jmax25 = vcmax25*jvr + case default + write (fates_log(),*)'error, incorrect leaf photosynthesis temperature acclimation model specified' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end select + + end if + co2_rcurve_islope25 = co2_rcurve_islope25top_ft * nscaler ! Adjust for temperature diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 71cc21af73..6eda5d6115 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -77,6 +77,7 @@ module EDParamsMod real(r8),protected, public :: ED_val_patch_fusion_tol ! minimum fraction in difference in profiles between patches real(r8),protected, public :: ED_val_canopy_closure_thresh ! site-level canopy closure point where trees take on forest (narrow) versus savannah (wide) crown allometry integer,protected, public :: stomatal_model ! switch for choosing between stomatal conductance models, 1 for Ball-Berry, 2 for Medlyn + integer,protected, public :: dayl_switch ! switch for turning on or off day length factor scaling for photosynthetic parameters integer,protected, public :: regeneration_model ! Switch for choosing between regeneration models: ! (1) for Fates default ! (2) for the Tree Recruitment Scheme (Hanbury-Brown et al., 2022) @@ -166,6 +167,7 @@ module EDParamsMod character(len=param_string_length),parameter,public :: ED_name_patch_fusion_tol= "fates_patch_fusion_tol" character(len=param_string_length),parameter,public :: ED_name_canopy_closure_thresh= "fates_canopy_closure_thresh" character(len=param_string_length),parameter,public :: ED_name_stomatal_model= "fates_leaf_stomatal_model" + character(len=param_string_length),parameter,public :: ED_name_dayl_switch= "fates_daylength_factor_switch" character(len=param_string_length),parameter,public :: ED_name_regeneration_model= "fates_regeneration_model" character(len=param_string_length),parameter,public :: name_theta_cj_c3 = "fates_leaf_theta_cj_c3" @@ -338,6 +340,7 @@ subroutine FatesParamsInit() ED_val_patch_fusion_tol = nan ED_val_canopy_closure_thresh = nan stomatal_model = -9 + dayl_switch = -9 regeneration_model = -9 stomatal_assim_model = -9 max_cohort_per_patch = -9 @@ -493,6 +496,9 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=ED_name_stomatal_model, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) + + call fates_params%RegisterParameter(name=ED_name_dayl_switch, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) call fates_params%RegisterParameter(name=ED_name_regeneration_model, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -715,6 +721,10 @@ subroutine FatesReceiveParams(fates_params) data=tmpreal) stomatal_model = nint(tmpreal) + call fates_params%RetrieveParameter(name=ED_name_dayl_switch, & + data=tmpreal) + dayl_switch = nint(tmpreal) + call fates_params%RetrieveParameter(name=ED_name_regeneration_model, & data=tmpreal) regeneration_model = nint(tmpreal) @@ -882,7 +892,8 @@ subroutine FatesReportParams(is_master) write(fates_log(),fmt0) 'ED_val_cohort_age_fusion_tol = ',ED_val_cohort_age_fusion_tol write(fates_log(),fmt0) 'ED_val_patch_fusion_tol = ',ED_val_patch_fusion_tol write(fates_log(),fmt0) 'ED_val_canopy_closure_thresh = ',ED_val_canopy_closure_thresh - write(fates_log(),fmt0) 'regeneration_model = ',regeneration_model + write(fates_log(),fmt0) 'regeneration_model = ',regeneration_model + write(fates_log(),fmt0) 'dayl_switch = ',dayl_switch write(fates_log(),fmt0) 'stomatal_model = ',stomatal_model write(fates_log(),fmt0) 'stomatal_assim_model = ',stomatal_assim_model write(fates_log(),fmt0) 'hydro_kmax_rsurf1 = ',hydr_kmax_rsurf1 diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 99bdaed02e..f664793c47 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -249,6 +249,9 @@ variables: double fates_damage_recovery_scalar(fates_pft) ; fates_damage_recovery_scalar:units = "unitless" ; fates_damage_recovery_scalar:long_name = "fraction of the cohort that recovers from damage" ; + double fates_daylength_factor_switch ; + fates_daylength_factor_switch:units = "unitless" ; + fates_daylength_factor_switch:long_name = "user switch for turning on (1) or off (2) the day length factor scaling for photosynthetic parameters" ; double fates_dev_arbitrary_pft(fates_pft) ; fates_dev_arbitrary_pft:units = "unknown" ; fates_dev_arbitrary_pft:long_name = "Unassociated pft dimensioned free parameter that developers can use for testing arbitrary new hypotheses" ; @@ -1613,6 +1616,8 @@ data: fates_damage_event_code = 1 ; + fates_daylength_factor_switch = 1 ; + fates_dev_arbitrary = _ ; fates_fire_active_crown_fire = 0 ; From 4b26a881462129c5444b86b7ebdc4ae651506d19 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 13 Mar 2024 16:32:03 -0700 Subject: [PATCH 2/6] refactoring the daylength factor application This reduces code duplication somewhat by updating a local value of the daylength factor based on the switch value. I also changed the switch to be zero for off and one for on to utilize the existing itrue/ifalse constants. --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 33 +++++++--------------- parameter_files/fates_params_default.cdl | 2 +- 2 files changed, 11 insertions(+), 24 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 1d947d74bb..b750dff1ab 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -110,10 +110,6 @@ module FATESPlantRespPhotosynthMod integer, parameter :: medlyn_model = 2 integer, parameter :: ballberry_model = 1 - ! Constants used to define day_length switch for scaling photosynthetic parameters - integer, parameter :: dayl_on = 1 - integer, parameter :: dayl_off = 2 - ! Alternatively, Gross Assimilation can be used to estimate ! leaf co2 partial pressure and therefore conductance. The default ! is to use anet @@ -2449,7 +2445,8 @@ subroutine LeafLayerBiophysicalRates( parsun_per_la, & ! (umol electrons/m**2/s) real(r8) :: co2_rcurve_islope25 ! leaf layer: Initial slope of CO2 response curve ! (C4 plants) at 25C - integer :: c3c4_path_index ! Index for which photosynthetic pathway + integer :: c3c4_path_index ! Index for which photosynthetic pathway + real(r8) :: dayl_factor_local ! Local version of daylength factor ! Parameters ! --------------------------------------------------------------------------------- @@ -2497,12 +2494,17 @@ subroutine LeafLayerBiophysicalRates( parsun_per_la, & co2_rcurve_islope = 0._r8 else ! day time - if ( dayl_switch == dayl_on ) then + if ( dayl_switch == itrue ) then + dayl_factor_local = dayl_factor + else + dayl_factor_local = 1.0_r8 + endif + ! Vcmax25top was already calculated to derive the nscaler function - vcmax25 = vcmax25top_ft * nscaler * dayl_factor + vcmax25 = vcmax25top_ft * nscaler * dayl_factor_local select case(photo_tempsens_model) case (photosynth_acclim_model_none) - jmax25 = jmax25top_ft * nscaler * dayl_factor + jmax25 = jmax25top_ft * nscaler * dayl_factor_local case (photosynth_acclim_model_kumarathunge_etal_2019) jmax25 = vcmax25*jvr case default @@ -2510,21 +2512,6 @@ subroutine LeafLayerBiophysicalRates( parsun_per_la, & call endrun(msg=errMsg(sourcefile, __LINE__)) end select - else if ( dayl_switch == dayl_off ) then - ! Vcmax25top was already calculated to derive the nscaler function - vcmax25 = vcmax25top_ft * nscaler - select case(photo_tempsens_model) - case (photosynth_acclim_model_none) - jmax25 = jmax25top_ft * nscaler - case (photosynth_acclim_model_kumarathunge_etal_2019) - jmax25 = vcmax25*jvr - case default - write (fates_log(),*)'error, incorrect leaf photosynthesis temperature acclimation model specified' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end select - - end if - co2_rcurve_islope25 = co2_rcurve_islope25top_ft * nscaler ! Adjust for temperature diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index f664793c47..e528654880 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -251,7 +251,7 @@ variables: fates_damage_recovery_scalar:long_name = "fraction of the cohort that recovers from damage" ; double fates_daylength_factor_switch ; fates_daylength_factor_switch:units = "unitless" ; - fates_daylength_factor_switch:long_name = "user switch for turning on (1) or off (2) the day length factor scaling for photosynthetic parameters" ; + fates_daylength_factor_switch:long_name = "user switch for turning on (1) or off (0) the day length factor scaling for photosynthetic parameters" ; double fates_dev_arbitrary_pft(fates_pft) ; fates_dev_arbitrary_pft:units = "unknown" ; fates_dev_arbitrary_pft:long_name = "Unassociated pft dimensioned free parameter that developers can use for testing arbitrary new hypotheses" ; From 02af1cb2092c45a55d98c4ea466c25339d055109 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 13 Mar 2024 16:34:52 -0700 Subject: [PATCH 3/6] add check to verify that the use supplied an appropriate parameter value for daylength switch --- main/EDPftvarcon.F90 | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 5745141c70..04db46c499 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1764,7 +1764,7 @@ subroutine FatesCheckParams(is_master) use FatesConstantsMod, only : lmr_r_2 use EDParamsMod , only : logging_mechanical_frac, logging_collateral_frac use EDParamsMod , only : logging_direct_frac,logging_export_frac - use EDParamsMod , only : radiation_model + use EDParamsMod , only : radiation_model, dayl_switch use FatesInterfaceTypesMod, only : hlm_use_fixed_biogeog,hlm_use_sp, hlm_name use FatesInterfaceTypesMod, only : hlm_use_inventory_init @@ -1810,6 +1810,13 @@ subroutine FatesCheckParams(is_master) call endrun(msg=errMsg(sourcefile, __LINE__)) end if + if(.not.any(dayl_switch == [itrue,ifalse])) then + write(fates_log(),*) 'The only valid switch options for ' + write(fates_log(),*) 'fates_daylength_factor_switch is 0 or 1 ...' + write(fates_log(),*) 'You specified fates_daylength_factor_switch = ',dayl_switch + write(fates_log(),*) 'Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if select case (hlm_parteh_mode) case (prt_cnp_flex_allom_hyp) From 482efe2074ba89cd5cffba880c71cd51b0f0ea89 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 13 Mar 2024 16:36:41 -0700 Subject: [PATCH 4/6] add code comment about daylength factor --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index b750dff1ab..caaced4556 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -2494,6 +2494,7 @@ subroutine LeafLayerBiophysicalRates( parsun_per_la, & co2_rcurve_islope = 0._r8 else ! day time + ! update the daylength factor local variable if the switch is on if ( dayl_switch == itrue ) then dayl_factor_local = dayl_factor else From 0633d1e6d3c63f9a9d3b13c5c954734bee00723a Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 21 Mar 2024 11:25:13 -0700 Subject: [PATCH 5/6] remove day length factor input to atkin subroutine --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 3 --- 1 file changed, 3 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index caaced4556..153db7f1f6 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -596,7 +596,6 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) nscaler, & ! in ft, & ! in bc_in(s)%t_veg_pa(ifp), & ! in - bc_in(s)%dayl_factor_pa(ifp), & ! in currentPatch%tveg_lpa%GetMean(), & ! in lmr_z(iv,ft,cl)) ! out @@ -2328,7 +2327,6 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & nscaler, & ft, & veg_tempk, & - dayl_factor, & tgrowth, & lmr) @@ -2347,7 +2345,6 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & integer, intent(in) :: ft ! (plant) Functional Type Index real(r8), intent(in) :: nscaler ! Scale for leaf nitrogen profile real(r8), intent(in) :: veg_tempk ! vegetation temperature (degrees K) - real(r8), intent(in) :: dayl_factor ! daylength scaling factor (0-1) real(r8), intent(in) :: tgrowth ! lagged vegetation temperature averaged over acclimation timescale (degrees K) real(r8), intent(out) :: lmr ! Leaf Maintenance Respiration (umol CO2/m**2/s) From a9b5230768353334446b7769c039963ee7e8159c Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 26 Apr 2024 06:40:26 -0600 Subject: [PATCH 6/6] reverting to parameter file from main, because daylength factor switch was already in there --- parameter_files/fates_params_default.cdl | 3 --- 1 file changed, 3 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 8a2997c300..2eaeb875fe 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -255,9 +255,6 @@ variables: double fates_damage_recovery_scalar(fates_pft) ; fates_damage_recovery_scalar:units = "unitless" ; fates_damage_recovery_scalar:long_name = "fraction of the cohort that recovers from damage" ; - double fates_daylength_factor_switch ; - fates_daylength_factor_switch:units = "unitless" ; - fates_daylength_factor_switch:long_name = "user switch for turning on (1) or off (0) the day length factor scaling for photosynthetic parameters" ; double fates_dev_arbitrary_pft(fates_pft) ; fates_dev_arbitrary_pft:units = "unknown" ; fates_dev_arbitrary_pft:long_name = "Unassociated pft dimensioned free parameter that developers can use for testing arbitrary new hypotheses" ;